<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <title>Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description">
<meta property="og:type" content="website">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="http://yoursite.com/page/12/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Hexo">
<meta name="twitter:description">
  
    <link rel="alternative" href="/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  <link rel="stylesheet" href="/css/style.css" type="text/css">
  

</head>
<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" results="0" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://yoursite.com"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main">
  
    <article id="post-redis/2.Redis系列之Java客户端" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/11/redis/2.Redis系列之Java客户端/" class="article-date">
  <time datetime="2015-12-11T05:00:00.000Z" itemprop="datePublished">2015-12-11</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/redis/">redis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/11/redis/2.Redis系列之Java客户端/">Redis系列二之Java客户端</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　Redis提供了Java，C/C++，C#，PHP，JavaScript，Perl，Object-C，Python，Ruby，Erlang等客户端，这样使我们很容易在项目中使用redis作为高效的缓存服务。在实际的使用中，开发或测试时使用的redis可能就是单节点的redis服务。在生产环境中，由于高可用和稳定性的需求，需要采用sentinel或者是shard的模式。在这种需求下，我们封装一个基于jedis库，便于操作Redis服务的客户端工具，方便在shard和sentinel等模式中无缝切换</p>
<h2 id="u5206_u6790"><a href="#u5206_u6790" class="headerlink" title="分析"></a>分析</h2><p>　　为支持shard模式，jedis提供了ShardedJedis类进行操作。<strong>注意，该类并非是继承自Jedis，并且Jedis和ShardedJedis提供的操作不同，可以理解为ShardedJedis的操作命令为Jedis提供的一个子集</strong>。在redis中，支持很多的命令，在参考jedis源码，如JedisCommands、MultiKeyCommands等的思想，抽象出两种Commands，一类用于Jedis、另一类则用于ShardedJedis，实现如下。由于操作命令太多，只选取最常用的get和set命令作为示例。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">ICommands</span>&lt;<span class="title">J</span>&gt; </span>&#123;</span><br><span class="line">    <span class="function">String <span class="title">get</span><span class="params">(String key)</span></span>;</span><br><span class="line">    <span class="function">String <span class="title">set</span><span class="params">(String key,String value)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Commands</span> <span class="keyword">implements</span> <span class="title">ICommands</span>&lt;<span class="title">Jedis</span>&gt; </span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> Pool&lt;Jedis&gt; pool;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">get</span><span class="params">(String key)</span></span>&#123;</span><br><span class="line">        Jedis jedis = <span class="keyword">null</span>;</span><br><span class="line">        String value = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            jedis = pool.getResource();</span><br><span class="line">            value = jedis.get(key);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            returnResource(jedis);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> value;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">set</span><span class="params">(String key, String value)</span></span>&#123;</span><br><span class="line">        Jedis jedis = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            jedis = pool.getResource();</span><br><span class="line">            <span class="keyword">return</span> jedis.set(key, value);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="string">"0"</span>;</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            returnResource(jedis);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ShardComands</span> <span class="keyword">implements</span> <span class="title">ICommands</span>&lt;<span class="title">ShardedJedis</span>&gt; </span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> Pool&lt;ShardedJedis&gt; pool;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">get</span><span class="params">(String key)</span></span>&#123;</span><br><span class="line">        ShardedJedis jedis = <span class="keyword">null</span>;</span><br><span class="line">        String value = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            jedis = pool.getResource();</span><br><span class="line">            value = jedis.get(key);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            returnResource(jedis);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> value;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">set</span><span class="params">(String key,String value)</span></span>&#123;</span><br><span class="line">        ShardedJedis jedis = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            jedis = pool.getResource();</span><br><span class="line">            <span class="keyword">return</span> jedis.set(key, value);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="string">"0"</span>;</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            returnResource(jedis);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　由于redis可以提供不同形式的服务，下面我们定义一个枚举，分别代表不同的形式<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">enum</span> ClientType &#123;</span><br><span class="line">    simple(<span class="number">1</span>),</span><br><span class="line">    sentinel(<span class="number">2</span>),</span><br><span class="line">    shard(<span class="number">3</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">int</span> type;</span><br><span class="line"></span><br><span class="line">    ClientType(<span class="keyword">int</span> type)&#123;</span><br><span class="line">        <span class="keyword">this</span>.type = type;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">value</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> type;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　服务的类型不同，客户端连接时所需要的参数也不尽相同。为统一方便，我们再实现一个类，用于封装所有的连接参数，此处只选取了三个必要的参数，大家可以自行完善。此处采用Builder的模式，方便初始化。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisConfig</span> </span>&#123;</span><br><span class="line">    ClientType clientType;</span><br><span class="line">    String masterName;</span><br><span class="line">    String[] servers;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">RedisConfig</span><span class="params">(ClientType clientType, String masterName, String[] servers)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.clientType = clientType;</span><br><span class="line">        <span class="keyword">this</span>.masterName = masterName;</span><br><span class="line">        <span class="keyword">this</span>.servers = servers;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> ClientType <span class="title">getClientType</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> clientType;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getMasterName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> masterName;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String[] getServers() &#123;</span><br><span class="line">        <span class="keyword">return</span> servers;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Builder</span></span>&#123;</span><br><span class="line">        ClientType clientType;</span><br><span class="line">        String masterName;</span><br><span class="line">        String[] servers;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Builder <span class="title">setClientType</span><span class="params">(ClientType clientType)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.clientType = clientType;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Builder <span class="title">setMasterName</span><span class="params">(String masterName)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.masterName = masterName;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Builder <span class="title">setServers</span><span class="params">(String... servers)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.servers = servers;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> RedisConfig <span class="title">build</span><span class="params">()</span></span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> RedisConfig(clientType, masterName, servers);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　下面开始封装三种客户端，代码如下<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisSimpleClient</span> <span class="keyword">extends</span> <span class="title">Commands</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">RedisSimpleClient</span><span class="params">(String ip, <span class="keyword">int</span> port)</span></span>&#123;</span><br><span class="line">        JedisPoolConfig config = <span class="keyword">new</span> JedisPoolConfig();</span><br><span class="line">        config.setMaxTotal(<span class="number">100</span>);</span><br><span class="line">        config.setMaxIdle(<span class="number">5</span>);</span><br><span class="line">        config.setTestOnBorrow(<span class="keyword">true</span>);</span><br><span class="line">        pool = <span class="keyword">new</span> JedisPool(config, ip, port, <span class="number">100000</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisSentinelClient</span> <span class="keyword">extends</span> <span class="title">Commands</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">RedisSentinelClient</span><span class="params">(String masterName, String... sentinels)</span></span>&#123;</span><br><span class="line">        <span class="keyword">assert</span> (masterName != <span class="keyword">null</span> &amp;&amp; masterName.trim().length() != <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">assert</span> (sentinels != <span class="keyword">null</span> &amp;&amp; sentinels.length &gt;<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">        Set&lt;String&gt; set = <span class="keyword">new</span> HashSet&lt;String&gt;();</span><br><span class="line">        <span class="keyword">for</span>(String sentinel : sentinels)&#123;</span><br><span class="line">            set.add(sentinel);</span><br><span class="line">        &#125;</span><br><span class="line">        pool = <span class="keyword">new</span> JedisSentinelPool(masterName, set);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisShardClient</span> <span class="keyword">extends</span> <span class="title">ShardComands</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">RedisShardClient</span><span class="params">(String... servers)</span></span>&#123;</span><br><span class="line">        List&lt;JedisShardInfo&gt; shards = <span class="keyword">new</span> ArrayList&lt;JedisShardInfo&gt;(servers.length);</span><br><span class="line">        <span class="keyword">for</span> (String server : servers)&#123;</span><br><span class="line">            List&lt;String&gt; item = Arrays.asList(server.split(<span class="string">":"</span>));</span><br><span class="line">            shards.add(<span class="keyword">new</span> JedisShardInfo(item.get(<span class="number">0</span>), Integer.valueOf(item.get(<span class="number">1</span>))));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        JedisPoolConfig config = <span class="keyword">new</span> JedisPoolConfig();</span><br><span class="line"></span><br><span class="line">        config.setMaxTotal(<span class="number">100</span>);</span><br><span class="line">        config.setMaxIdle(<span class="number">5</span>);</span><br><span class="line">        config.setTestOnBorrow(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 构造池</span></span><br><span class="line">        pool = <span class="keyword">new</span> ShardedJedisPool(config, shards);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　下面我们采用工厂类的模式，简化客户端初始化的工作，代码如下<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisClientFactory</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Map&lt;ClientType, Class&lt;? extends IClientFactory&gt;&gt; factoryMap = <span class="keyword">new</span> HashMap&lt;ClientType, Class&lt;? extends IClientFactory&gt;&gt;()&#123;&#123;</span><br><span class="line">        put(ClientType.simple, SimpleClientFactory.class);</span><br><span class="line">        put(ClientType.sentinel, SentinelClientFactory.class);</span><br><span class="line">        put(ClientType.shard, ShardClientFactory.class);</span><br><span class="line">    &#125;&#125;;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> ICommands <span class="title">createClient</span><span class="params">(RedisConfig config)</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(config == <span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"RedisClientFactory.createClient方法参数不可为空"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        ClientType clientType = config.getClientType();</span><br><span class="line">        <span class="keyword">if</span>(clientType == <span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"请指定ClientType类型"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        String masterName = config.getMasterName();</span><br><span class="line">        <span class="keyword">if</span>(clientType == ClientType.sentinel &amp;&amp; (masterName == <span class="keyword">null</span> || masterName.trim().length() == <span class="number">0</span>))&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"redis sentinel模式必须指定masterName"</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        String[] servers = config.getServers();</span><br><span class="line">        <span class="keyword">if</span>(servers == <span class="keyword">null</span> || servers.length == <span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"请指定redis服务的地址，形如：host:port;host:port;host:port"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            IClientFactory clientFactory = factoryMap.get(config.getClientType()).newInstance();</span><br><span class="line">            <span class="keyword">return</span> clientFactory.createClient(config);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InstantiationException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IllegalAccessException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">IClientFactory</span></span>&#123;</span><br><span class="line">        <span class="function">ICommands <span class="title">createClient</span><span class="params">(RedisConfig redisConfig)</span></span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">SimpleClientFactory</span> <span class="keyword">implements</span> <span class="title">IClientFactory</span></span>&#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> ICommands <span class="title">createClient</span><span class="params">(RedisConfig redisConfig)</span> </span>&#123;</span><br><span class="line">            String server = redisConfig.getServers()[<span class="number">0</span>];</span><br><span class="line">            List&lt;String&gt; list = Arrays.asList(server.split(<span class="string">":"</span>));</span><br><span class="line">            <span class="keyword">if</span>(list == <span class="keyword">null</span> || list.size() != <span class="number">2</span>)&#123;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"redis服务地址错误，"</span> + server + <span class="string">"，应形如host:port"</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> RedisSimpleClient(list.get(<span class="number">0</span>), Integer.valueOf(list.get(<span class="number">1</span>)));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">SentinelClientFactory</span> <span class="keyword">implements</span> <span class="title">IClientFactory</span></span>&#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> ICommands <span class="title">createClient</span><span class="params">(RedisConfig redisConfig)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> RedisSentinelClient(redisConfig.getMasterName(), redisConfig.getServers());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ShardClientFactory</span> <span class="keyword">implements</span> <span class="title">IClientFactory</span></span>&#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> ICommands <span class="title">createClient</span><span class="params">(RedisConfig redisConfig)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> RedisShardClient(redisConfig.getServers());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　到这里封装基本上也就完成了，调用代码如下<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//sentinel连接模式</span></span><br><span class="line">RedisConfig config = <span class="keyword">new</span> RedisConfig.Builder()</span><br><span class="line">        .setClientType(ClientType.sentinel)</span><br><span class="line">        .setMasterName(<span class="string">"master1"</span>)</span><br><span class="line">        .setServers(<span class="string">"192.168.85.64:26379"</span>, <span class="string">"192.168.85.64:26479"</span>, <span class="string">"192.168.85.64:26579"</span>)</span><br><span class="line">        .build();</span><br><span class="line">redisClient = RedisClientFactory.createClient(config);</span><br><span class="line">		</span><br><span class="line"><span class="comment">//shard连接模式</span></span><br><span class="line">RedisConfig config = <span class="keyword">new</span> RedisConfig.Builder()</span><br><span class="line">        .setClientType(ClientType.shard)</span><br><span class="line">        .setServers(<span class="string">"192.168.85.64:6401"</span>, <span class="string">"192.168.85.64:6402"</span>, <span class="string">"192.168.85.64:6403"</span>)</span><br><span class="line">        .build();</span><br><span class="line">redisClient = RedisClientFactory.createClient(config);</span><br><span class="line">		</span><br><span class="line"><span class="comment">//单节点连接模式</span></span><br><span class="line">RedisConfig config = <span class="keyword">new</span> RedisConfig.Builder()</span><br><span class="line">        .setClientType(ClientType.simple)</span><br><span class="line">        .setServers(<span class="string">"192.168.85.64:6379"</span>)</span><br><span class="line">        .build();</span><br><span class="line">redisClient = RedisClientFactory.createClient(config);</span><br></pre></td></tr></table></figure></p>
<p>　　到此大功告成！！！！！！源码下载地址：<a href="/code/redis-client.zip">redis-client.zip</a></p>
<h2 id="u53C2_u8003_u8D44_u6599"><a href="#u53C2_u8003_u8D44_u6599" class="headerlink" title="参考资料"></a>参考资料</h2><p><a href="http://www.blogjava.net/bjwulin/archive/2014/02/08/409621.html" target="_blank" rel="external">http://www.blogjava.net/bjwulin/archive/2014/02/08/409621.html</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/11/redis/2.Redis系列之Java客户端/" data-id="cijzzpv6300421cfsrn4z9z9g" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/redis/">redis</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-redis/1.Redis系列之入门" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/11/redis/1.Redis系列之入门/" class="article-date">
  <time datetime="2015-12-11T04:00:00.000Z" itemprop="datePublished">2015-12-11</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/redis/">redis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/11/redis/1.Redis系列之入门/">Redis系列一之入门</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　redis是一个key-value存储系统。和Memcached类似，它支持存储的value类型相对更多，包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash（哈希类型）。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作，而且这些操作都是原子性的。在此基础上，redis支持各种不同方式的排序。与memcached一样，为了保证效率，数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件，并且在此基础上实现了master-slave(主从)同步。<br>　　本篇文章将介绍redis在单个centos下的编译安装与配置，包括单节点配置、master-slave配置、shard配置（其实就是单节点配置，只是端口和db路径不同罢了）。在下一篇文章中，我们将采用java的jedis客户端进行连接、测试，验证配置的有效性！</p>
<h2 id="u7F16_u8BD1_u5B89_u88C5"><a href="#u7F16_u8BD1_u5B89_u88C5" class="headerlink" title="编译安装"></a>编译安装</h2><p>　　通过如下命令即可在centos下安装redis。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">wget http://download.redis.io/releases/redis-<span class="number">2.8</span>.<span class="number">19</span>.tar.gz</span><br><span class="line">tar xzf redis-<span class="number">2.8</span>.<span class="number">19</span>.tar.gz</span><br><span class="line">mv redis-<span class="number">2.8</span>.<span class="number">19</span>.tar.gz redis</span><br><span class="line"><span class="built_in">cd</span> redis</span><br><span class="line">make</span><br></pre></td></tr></table></figure></p>
<p>　　编译完成后，在src目录下，有五个可执行文件redis-server、redis-benchmark、redis-cli、redis-check-dump、redis-check-aof和redis-sentinel。将他们拷贝到redis/bin目录下即可（需要在redis下新建bin目录）。同时将redis目录下的redis.conf和sentinel.conf文件拷贝到redis/bin目录下</p>
<h2 id="redis_u914D_u7F6E_u89C4_u5212"><a href="#redis_u914D_u7F6E_u89C4_u5212" class="headerlink" title="redis配置规划"></a>redis配置规划</h2><p>　　在此次安装中，我们将在单机模式下进行master-slaver和sentinel模式的配置，服务器内网地址为：192.168.85.64。下表记录了配置的目录和端口等信息。</p>
<table>
<thead>
<tr>
<th style="text-align:left">节点类型</th>
<th style="text-align:left">端口</th>
<th style="text-align:left">配置文件</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">master</td>
<td style="text-align:left">6379</td>
<td style="text-align:left">redis/bin/conf/redis-master-6379.conf</td>
</tr>
<tr>
<td style="text-align:left">slaver1</td>
<td style="text-align:left">6380</td>
<td style="text-align:left">redis/bin/conf/redis-slave1-6380.conf</td>
</tr>
<tr>
<td style="text-align:left">slaver2</td>
<td style="text-align:left">6381</td>
<td style="text-align:left">redis/bin/conf/redis-slave2-6381.conf</td>
</tr>
<tr>
<td style="text-align:left">slaver3</td>
<td style="text-align:left">6382</td>
<td style="text-align:left">redis/bin/conf/redis-slave3-6382.conf</td>
</tr>
<tr>
<td style="text-align:left">sentinel1</td>
<td style="text-align:left">26379</td>
<td style="text-align:left">redis/bin/conf/sentinel-26379.conf</td>
</tr>
<tr>
<td style="text-align:left">sentinel2</td>
<td style="text-align:left">26479</td>
<td style="text-align:left">redis/bin/conf/sentinel-26479.conf</td>
</tr>
<tr>
<td style="text-align:left">sentinel3</td>
<td style="text-align:left">26579</td>
<td style="text-align:left">redis/bin/conf/sentinel-26579.conf</td>
</tr>
</tbody>
</table>
<h2 id="master_u914D_u7F6E"><a href="#master_u914D_u7F6E" class="headerlink" title="master配置"></a>master配置</h2><p>　　master配置文件：redis-master-6379.conf。实际上只是调整了redis.conf配置文件的几个默认属性：daemonize、pidfile、logfile、dbfilename、dir等<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">daemonize yes</span><br><span class="line">pidfile ./run/redis_master_6379.pid</span><br><span class="line">port 6379</span><br><span class="line">tcp-backlog 511</span><br><span class="line">timeout 0</span><br><span class="line">tcp-keepalive 0</span><br><span class="line">loglevel notice</span><br><span class="line">logfile "./logs/master_6379.log"</span><br><span class="line">databases 16</span><br><span class="line"></span><br><span class="line">save ""</span><br><span class="line"><span class="operator"><span class="keyword">stop</span>-writes-<span class="keyword">on</span>-bgsave-<span class="keyword">error</span> yes</span><br><span class="line">rdbcompression yes</span><br><span class="line">rdbchecksum yes</span><br><span class="line">dbfilename dump_master_6379.rdb</span><br><span class="line">dir ./db</span><br><span class="line"></span><br><span class="line"><span class="keyword">slave</span>-serve-stale-<span class="keyword">data</span> yes</span><br><span class="line"><span class="keyword">slave</span>-<span class="keyword">read</span>-<span class="keyword">only</span> yes</span><br><span class="line">repl-diskless-<span class="keyword">sync</span> <span class="keyword">no</span></span><br><span class="line">repl-diskless-<span class="keyword">sync</span>-delay <span class="number">5</span></span><br><span class="line">repl-<span class="keyword">disable</span>-tcp-<span class="keyword">nodelay</span> <span class="keyword">no</span></span><br><span class="line"><span class="keyword">slave</span>-<span class="keyword">priority</span> <span class="number">100</span></span><br><span class="line"></span><br><span class="line">appendonly <span class="keyword">no</span></span><br><span class="line">appendfilename <span class="string">"appendonly_master_6379.aof"</span></span><br><span class="line">appendfsync <span class="keyword">no</span></span><br><span class="line"><span class="keyword">no</span>-appendfsync-<span class="keyword">on</span>-rewrite <span class="keyword">no</span></span><br><span class="line"><span class="keyword">auto</span>-aof-rewrite-percentage <span class="number">100</span></span><br><span class="line"><span class="keyword">auto</span>-aof-rewrite-<span class="keyword">min</span>-<span class="keyword">size</span> <span class="number">64</span>mb</span><br><span class="line">aof-<span class="keyword">load</span>-truncated yes</span><br><span class="line"></span><br><span class="line">lua-<span class="keyword">time</span>-<span class="keyword">limit</span> <span class="number">5000</span></span><br><span class="line"></span><br><span class="line">slowlog-<span class="keyword">log</span>-slower-<span class="keyword">than</span> <span class="number">10000</span></span><br><span class="line">slowlog-<span class="keyword">max</span>-<span class="keyword">len</span> <span class="number">128</span></span><br><span class="line"></span><br><span class="line">latency-monitor-threshold <span class="number">0</span></span><br><span class="line"></span><br><span class="line">notify-keyspace-<span class="keyword">events</span> <span class="string">""</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">hash</span>-<span class="keyword">max</span>-ziplist-entries <span class="number">512</span></span><br><span class="line"><span class="keyword">hash</span>-<span class="keyword">max</span>-ziplist-<span class="keyword">value</span> <span class="number">64</span></span><br><span class="line"><span class="keyword">list</span>-<span class="keyword">max</span>-ziplist-entries <span class="number">512</span></span><br><span class="line"><span class="keyword">list</span>-<span class="keyword">max</span>-ziplist-<span class="keyword">value</span> <span class="number">64</span></span><br><span class="line"><span class="keyword">set</span>-<span class="keyword">max</span>-intset-entries <span class="number">512</span></span><br><span class="line">zset-<span class="keyword">max</span>-ziplist-entries <span class="number">128</span></span><br><span class="line">zset-<span class="keyword">max</span>-ziplist-<span class="keyword">value</span> <span class="number">64</span></span><br><span class="line">hll-<span class="keyword">sparse</span>-<span class="keyword">max</span>-<span class="keyword">bytes</span> <span class="number">3000</span></span><br><span class="line">activerehashing yes</span><br><span class="line"><span class="keyword">client</span>-<span class="keyword">output</span>-buffer-<span class="keyword">limit</span> <span class="keyword">normal</span> <span class="number">0</span> <span class="number">0</span> <span class="number">0</span></span><br><span class="line"><span class="keyword">client</span>-<span class="keyword">output</span>-buffer-<span class="keyword">limit</span> <span class="keyword">slave</span> <span class="number">256</span>mb <span class="number">64</span>mb <span class="number">60</span></span><br><span class="line"><span class="keyword">client</span>-<span class="keyword">output</span>-buffer-<span class="keyword">limit</span> pubsub <span class="number">32</span>mb <span class="number">8</span>mb <span class="number">60</span></span><br><span class="line">hz <span class="number">10</span></span><br><span class="line">aof-rewrite-incremental-fsync yes</span></span><br></pre></td></tr></table></figure></p>
<h2 id="slaver_u914D_u7F6E"><a href="#slaver_u914D_u7F6E" class="headerlink" title="slaver配置"></a>slaver配置</h2><p>　　slaver配置文件：redis-slave1-6380.conf。实际上只是调整了redis.conf配置文件的几个默认属性：daemonize、pidfile、port、logfile、dbfilename、dir，同时制定了slaveof属性。另外两个salver配置文件redis-slave2-6381.conf和redis-slave3-6382.conf只需要修改slaver1的配置pidfile、port、logfile、dbfilename、appendfilename即可。注意，由于是运行在同一个机器上，各个属性值不能相同<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">daemonize yes</span><br><span class="line">pidfile "./run/redis_slave1_6380.pid"</span><br><span class="line">port 6380</span><br><span class="line">tcp-backlog 511</span><br><span class="line">timeout 0</span><br><span class="line">tcp-keepalive 0</span><br><span class="line">loglevel notice</span><br><span class="line">logfile "./logs/slave1_6380.log"</span><br><span class="line">databases 16</span><br><span class="line"></span><br><span class="line"><span class="operator"><span class="keyword">stop</span>-writes-<span class="keyword">on</span>-bgsave-<span class="keyword">error</span> yes</span><br><span class="line">rdbcompression yes</span><br><span class="line">rdbchecksum <span class="keyword">no</span></span><br><span class="line">dbfilename <span class="string">"dump_slave1_6380.rdb"</span></span><br><span class="line">dir <span class="string">"/mapbar/redis/redis/bin/db"</span></span><br><span class="line"></span><br><span class="line">slaveof <span class="number">192.168</span><span class="number">.85</span><span class="number">.64</span> <span class="number">6379</span></span><br><span class="line"><span class="keyword">slave</span>-serve-stale-<span class="keyword">data</span> yes</span><br><span class="line"><span class="keyword">slave</span>-<span class="keyword">read</span>-<span class="keyword">only</span> yes</span><br><span class="line">repl-diskless-<span class="keyword">sync</span> <span class="keyword">no</span></span><br><span class="line">repl-diskless-<span class="keyword">sync</span>-delay <span class="number">5</span></span><br><span class="line">repl-<span class="keyword">disable</span>-tcp-<span class="keyword">nodelay</span> <span class="keyword">no</span></span><br><span class="line"><span class="keyword">slave</span>-<span class="keyword">priority</span> <span class="number">80</span></span><br><span class="line"></span><br><span class="line">appendonly <span class="keyword">no</span></span><br><span class="line">appendfilename <span class="string">"appendonly_slave1_6380.aof"</span></span><br><span class="line">appendfsync <span class="keyword">no</span></span><br><span class="line"><span class="keyword">no</span>-appendfsync-<span class="keyword">on</span>-rewrite <span class="keyword">no</span></span><br><span class="line"><span class="keyword">auto</span>-aof-rewrite-percentage <span class="number">100</span></span><br><span class="line"><span class="keyword">auto</span>-aof-rewrite-<span class="keyword">min</span>-<span class="keyword">size</span> <span class="number">64</span>mb</span><br><span class="line">aof-<span class="keyword">load</span>-truncated yes</span><br><span class="line"></span><br><span class="line">lua-<span class="keyword">time</span>-<span class="keyword">limit</span> <span class="number">5000</span></span><br><span class="line"></span><br><span class="line">slowlog-<span class="keyword">log</span>-slower-<span class="keyword">than</span> <span class="number">10000</span></span><br><span class="line">slowlog-<span class="keyword">max</span>-<span class="keyword">len</span> <span class="number">128</span></span><br><span class="line"></span><br><span class="line">latency-monitor-threshold <span class="number">0</span></span><br><span class="line"></span><br><span class="line">notify-keyspace-<span class="keyword">events</span> <span class="string">""</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">hash</span>-<span class="keyword">max</span>-ziplist-entries <span class="number">512</span></span><br><span class="line"><span class="keyword">hash</span>-<span class="keyword">max</span>-ziplist-<span class="keyword">value</span> <span class="number">64</span></span><br><span class="line"><span class="keyword">list</span>-<span class="keyword">max</span>-ziplist-entries <span class="number">512</span></span><br><span class="line"><span class="keyword">list</span>-<span class="keyword">max</span>-ziplist-<span class="keyword">value</span> <span class="number">64</span></span><br><span class="line"><span class="keyword">set</span>-<span class="keyword">max</span>-intset-entries <span class="number">512</span></span><br><span class="line">zset-<span class="keyword">max</span>-ziplist-entries <span class="number">128</span></span><br><span class="line">zset-<span class="keyword">max</span>-ziplist-<span class="keyword">value</span> <span class="number">64</span></span><br><span class="line">hll-<span class="keyword">sparse</span>-<span class="keyword">max</span>-<span class="keyword">bytes</span> <span class="number">3000</span></span><br><span class="line">activerehashing yes</span><br><span class="line"><span class="keyword">client</span>-<span class="keyword">output</span>-buffer-<span class="keyword">limit</span> <span class="keyword">normal</span> <span class="number">0</span> <span class="number">0</span> <span class="number">0</span></span><br><span class="line"><span class="keyword">client</span>-<span class="keyword">output</span>-buffer-<span class="keyword">limit</span> <span class="keyword">slave</span> <span class="number">256</span>mb <span class="number">64</span>mb <span class="number">60</span></span><br><span class="line"><span class="keyword">client</span>-<span class="keyword">output</span>-buffer-<span class="keyword">limit</span> pubsub <span class="number">32</span>mb <span class="number">8</span>mb <span class="number">60</span></span><br><span class="line">hz <span class="number">10</span></span><br><span class="line">aof-rewrite-incremental-fsync yes</span></span><br></pre></td></tr></table></figure></p>
<h2 id="sentinel_u914D_u7F6E"><a href="#sentinel_u914D_u7F6E" class="headerlink" title="sentinel配置"></a>sentinel配置</h2><p>　　sentinel1节点配置文件为：sentinel-26379.conf，输入如下内容<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">port <span class="number">26379</span></span><br><span class="line">dir <span class="string">"./db/26379"</span></span><br><span class="line">sentinel monitor master1 <span class="number">192.168</span><span class="number">.85</span><span class="number">.64</span> <span class="number">6379</span> <span class="number">2</span></span><br><span class="line">sentinel down-after-milliseconds master1 <span class="number">30000</span></span><br><span class="line">sentinel parallel-syncs master1 <span class="number">1</span></span><br><span class="line">sentinel failover-timeout master1 <span class="number">180000</span></span><br><span class="line">logfile <span class="string">"/tmp/sentinellog__26379.log"</span></span><br></pre></td></tr></table></figure></p>
<p>　　sentinel2节点配置文件为：sentinel-26479.conf，输入如下内容<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">port <span class="number">26479</span></span><br><span class="line">dir <span class="string">"./db/26479"</span></span><br><span class="line">sentinel monitor master1 <span class="number">192.168</span><span class="number">.85</span><span class="number">.64</span> <span class="number">6379</span> <span class="number">2</span></span><br><span class="line">sentinel down-after-milliseconds master1 <span class="number">30000</span></span><br><span class="line">sentinel parallel-syncs master1 <span class="number">1</span></span><br><span class="line">sentinel failover-timeout master1 <span class="number">180000</span></span><br><span class="line">logfile <span class="string">"/tmp/sentinellog__26479.log"</span></span><br></pre></td></tr></table></figure></p>
<p>　　sentinel3节点配置文件为：sentinel-26579.conf，输入如下内容<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">port <span class="number">26579</span></span><br><span class="line">dir <span class="string">"./db/26579"</span></span><br><span class="line">sentinel monitor master1 <span class="number">192.168</span><span class="number">.85</span><span class="number">.64</span> <span class="number">6379</span> <span class="number">2</span></span><br><span class="line">sentinel down-after-milliseconds master1 <span class="number">30000</span></span><br><span class="line">sentinel parallel-syncs master1 <span class="number">1</span></span><br><span class="line">sentinel failover-timeout master1 <span class="number">180000</span></span><br><span class="line">logfile <span class="string">"/tmp/sentinellog__26579.log"</span></span><br></pre></td></tr></table></figure></p>
<h2 id="u542F_u52A8_u670D_u52A1"><a href="#u542F_u52A8_u670D_u52A1" class="headerlink" title="启动服务"></a>启动服务</h2><p>master节点<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./redis-server ./conf/redis-master-<span class="number">6379</span>.conf &amp;</span><br></pre></td></tr></table></figure></p>
<p>slaver1节点<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./redis-server ./conf/redis-slave1-<span class="number">6380</span>.conf &amp;</span><br></pre></td></tr></table></figure></p>
<p>slaver2节点<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./redis-server ./conf/redis-slave2-<span class="number">6381</span>.conf &amp;</span><br></pre></td></tr></table></figure></p>
<p>slaver3节点<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./redis-server ./conf/redis-slave3-<span class="number">6382</span>.conf &amp;</span><br></pre></td></tr></table></figure></p>
<p>sentinel1节点<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./redis-sentinel ./conf/sentinel-<span class="number">26379</span>.conf &amp;</span><br></pre></td></tr></table></figure></p>
<p>sentinel2节<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./redis-sentinel ./conf/sentinel-<span class="number">26479</span>.conf &amp;</span><br></pre></td></tr></table></figure></p>
<p>sentinel3节点<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./redis-sentinel ./conf/sentinel-<span class="number">26579</span>.conf &amp;</span><br></pre></td></tr></table></figure></p>
<h2 id="u5173_u95ED_u670D_u52A1"><a href="#u5173_u95ED_u670D_u52A1" class="headerlink" title="关闭服务"></a>关闭服务</h2><p>　　redis-cli shutdown 或者直接在启动服务的端口中直接Ctrl+C。如果不是默认的端口，则需要指定端口号：redis-cli -p 6382 shutdown</p>
<p>　　到这里配置完成了，下一篇文章我们将通过java客户端验证配置的正确性。注意，在实际使用的过程中，会发现如果服务器宕机，由于配置sentinel，此时会自动从slave中选取一个master。这样会导致原配置文件发生变化，切记！！！完整的配置文件如下：待补充</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/11/redis/1.Redis系列之入门/" data-id="cijzzpv6700451cfsnrnx0nvn" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/redis/">redis</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-mybatis/9.Mybatis系列之负载均衡与读写分离" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/09/mybatis/9.Mybatis系列之负载均衡与读写分离/" class="article-date">
  <time datetime="2015-12-09T11:00:00.000Z" itemprop="datePublished">2015-12-09</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/mybatis/">mybatis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/09/mybatis/9.Mybatis系列之负载均衡与读写分离/">Mybatis系列九之负载均衡与读写分析</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u9700_u6C42"><a href="#u9700_u6C42" class="headerlink" title="需求"></a>需求</h2><p>　　假设如下场景：移动终端APP用户量很大，需要进行大量的查询操作，此时对数据库产生了较大的查询压力。此时，可以在数据库端采用一主多从的模式。如果后台查询服务能够在从库之间动态的进行负载均衡，则可以分散从库的查询压力。此时我们该怎么做呢？<br>　　这时，我们就需要引入spring的AbstractRoutingDataSource数据源了。顾名思义，该数据源就是一个进行路由的数据源，我们只需要将所有的从库配置到该数据源中即可。该路由数据源自动选取一个数据源进行查询操作即可！</p>
<h2 id="u5B9E_u73B0"><a href="#u5B9E_u73B0" class="headerlink" title="实现"></a>实现</h2><p>　　首先，实现一个LoadBalanceDataSource，该类将根据负载数据库的数量，采用求模取余的方式，返回某个数据源的标识，如下所示：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LoadBalanceDataSource</span> <span class="keyword">extends</span> <span class="title">AbstractRoutingDataSource</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Lock lock = <span class="keyword">new</span> ReentrantLock();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> counter = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> dataSourceNumber = <span class="number">3</span>;</span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> Object <span class="title">determineCurrentLookupKey</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        lock.lock();</span><br><span class="line">        <span class="keyword">try</span>&#123;</span><br><span class="line">            counter++;</span><br><span class="line">            <span class="keyword">int</span> lookupKey = counter % dataSourceNumber + <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">return</span> String.valueOf(<span class="keyword">new</span> Integer(lookupKey));</span><br><span class="line">        &#125;<span class="keyword">finally</span>&#123;</span><br><span class="line">            lock.unlock();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="u6570_u636E_u6E90_u914D_u7F6E"><a href="#u6570_u636E_u6E90_u914D_u7F6E" class="headerlink" title="数据源配置"></a>数据源配置</h2><p>　　假设我们有三个从库，连接参数详见配置文件spring-loadbalance.xml。注意，此处为了方便，实际上三个数据库都在一个节点上，只是数据库名不同罢了。<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--数据库属性配置--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource1"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://localhost:3306/loadbalance1"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"="</span><span class="value">****""</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource2"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://localhost:3306/loadbalance2"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"****"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource3"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://localhost:3306/loadbalance3"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"="</span><span class="value">****""</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="title">util:map</span> <span class="attribute">id</span>=<span class="value">"dataSources"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"1"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource1"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"2"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource2"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"3"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource3"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">util:map</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSourceLookup"</span> <span class="attribute">class</span>=<span class="value">"org.springframework.jdbc.datasource.lookup.MapDataSourceLookup"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">constructor-arg</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="title">ref</span> <span class="attribute">bean</span>=<span class="value">"dataSources"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="title">constructor-arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource"</span> <span class="attribute">class</span>=<span class="value">"com.shc.db.loadbalance.datasource.LoadBalanceDataSource"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"defaultTargetDataSource"</span> <span class="attribute">ref</span>=<span class="value">"dataSource1"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"targetDataSources"</span> <span class="attribute">ref</span>=<span class="value">"dataSources"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"dataSourceLookup"</span> <span class="attribute">ref</span>=<span class="value">"dataSourceLookup"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"jdbcTemplate"</span> <span class="attribute">class</span>=<span class="value">"org.springframework.jdbc.core.JdbcTemplate"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"dataSource"</span> <span class="attribute">ref</span>=<span class="value">"dataSource"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　从上面的配置可以看出，三个进行负载均衡的数据库，最后都注入到了LoadBalanceDataSource。在AbstractRoutingDataSource的方法determineTargetDataSource中，我们可以看到首先调用determineCurrentLookupKey（我们重载的方法）获取一个key，再根据该key从resolvedDataSources（Map类型，key为String类型，这也就解释了为什么LoadBalanceDataSource中重载determineCurrentLookupKey方法时，返回的是一个字符串，而不能是整形）中找到一个数据源，如果没找到，则采用默认的数据源。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">protected</span> DataSource <span class="title">determineTargetDataSource</span><span class="params">()</span> </span>&#123;</span><br><span class="line">	Assert.notNull(<span class="keyword">this</span>.resolvedDataSources, <span class="string">"DataSource router not initialized"</span>);</span><br><span class="line">	Object lookupKey = determineCurrentLookupKey();</span><br><span class="line">	DataSource dataSource = <span class="keyword">this</span>.resolvedDataSources.get(lookupKey);</span><br><span class="line">	<span class="keyword">if</span> (dataSource == <span class="keyword">null</span> &amp;&amp; (<span class="keyword">this</span>.lenientFallback || lookupKey == <span class="keyword">null</span>)) &#123;</span><br><span class="line">		dataSource = <span class="keyword">this</span>.resolvedDefaultDataSource;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">if</span> (dataSource == <span class="keyword">null</span>) &#123;</span><br><span class="line">		<span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(<span class="string">"Cannot determine target DataSource for lookup key ["</span> + lookupKey + <span class="string">"]"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> dataSource;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="u6570_u636E_u5E93_u914D_u7F6E"><a href="#u6570_u636E_u5E93_u914D_u7F6E" class="headerlink" title="数据库配置"></a>数据库配置</h2><p>　　我们同时在三个数据库loadbalance1、loadbalance2、loadbalance3中建表test，并分别插入一条数据<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="keyword">test</span>(</span><br><span class="line">	<span class="keyword">id</span> <span class="built_in">INT</span>,</span><br><span class="line">	<span class="keyword">name</span> <span class="built_in">VARCHAR</span>(<span class="number">32</span>)</span><br><span class="line">);</span></span><br><span class="line"><span class="comment">-- 插入loadbalance1</span></span><br><span class="line"><span class="operator"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> <span class="keyword">test</span>(<span class="keyword">id</span>, <span class="keyword">name</span>) <span class="keyword">VALUES</span>(<span class="number">1</span>, <span class="string">"loadbalance1数据"</span>);</span></span><br><span class="line"><span class="comment">-- 插入loadbalance2</span></span><br><span class="line"><span class="operator"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> <span class="keyword">test</span>(<span class="keyword">id</span>, <span class="keyword">name</span>) <span class="keyword">VALUES</span>(<span class="number">1</span>, <span class="string">"loadbalance2数据"</span>);</span></span><br><span class="line"><span class="comment">-- 插入loadbalance3</span></span><br><span class="line"><span class="operator"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> <span class="keyword">test</span>(<span class="keyword">id</span>, <span class="keyword">name</span>) <span class="keyword">VALUES</span>(<span class="number">1</span>, <span class="string">"loadbalance3数据"</span>);</span></span><br></pre></td></tr></table></figure></p>
<h2 id="u6D4B_u8BD5_u4EE3_u7801"><a href="#u6D4B_u8BD5_u4EE3_u7801" class="headerlink" title="测试代码"></a>测试代码</h2><p>　　这里我们采用junit进行单元测试<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LoadBalanceTest</span> </span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> ApplicationContext ac;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Before</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">()</span></span>&#123;</span><br><span class="line">        ac = <span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="keyword">new</span> String[]&#123;<span class="string">"spring-loadbalance.xml"</span>&#125;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">query1</span><span class="params">()</span></span>&#123;</span><br><span class="line">        QueryService service = ac.getBean(QueryService.class);</span><br><span class="line">        service.queryData();</span><br><span class="line">        service.queryData();</span><br><span class="line">        service.queryData();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>执行后输出如下：<br>[{id=1, name=loadbalance2数据}]<br>[{id=1, name=loadbalance3数据}]<br>[{id=1, name=loadbalance1数据}]</p>
<h2 id="u4E3B_u4ECE_u5207_u6362"><a href="#u4E3B_u4ECE_u5207_u6362" class="headerlink" title="主从切换"></a>主从切换</h2><p>　　接下来，我们将上面的例子稍作调整，就可以实现一主多从，读写分离的功能。首先，我们再次实现AbstractRoutingDataSource类，<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DynamicDataSource</span> <span class="keyword">extends</span> <span class="title">AbstractRoutingDataSource</span> </span>&#123;</span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> Object <span class="title">determineCurrentLookupKey</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> JdbcContextHolder.getJdbcType();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">JdbcContextHolder</span> </span>&#123;</span><br><span class="line">        <span class="comment">//采用ThreadLocal实现多线程安全</span></span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> ThreadLocal&lt;String&gt; contextHolder = <span class="keyword">new</span> ThreadLocal&lt;String&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">setJdbcType</span><span class="params">(String jdbcType)</span> </span>&#123;</span><br><span class="line">            contextHolder.set(jdbcType);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">setSlave</span><span class="params">(String salveName)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">            setJdbcType(salveName);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">setMaster</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            clearJdbcType();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getJdbcType</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> (String) contextHolder.get();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">clearJdbcType</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            contextHolder.remove();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　接着定义spring配置文件spring-dynamicDS.xml，这里仍然采用上面的三个数据库，假设loadbalance3为主库，loadbalance1和loadbalance2为从库。<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"master"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance3"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"slave1"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance1"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"slave2"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance2"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"mySqlDataSource"</span> <span class="attribute">class</span>=<span class="value">"com.shc.db.loadbalance.datasource.DynamicDataSource"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"targetDataSources"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="title">map</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"slave1"</span> <span class="attribute">value-ref</span>=<span class="value">"slave1"</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"slave2"</span> <span class="attribute">value-ref</span>=<span class="value">"slave2"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="title">map</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="title">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"defaultTargetDataSource"</span> <span class="attribute">ref</span>=<span class="value">"master"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"jdbcTemplate"</span> <span class="attribute">class</span>=<span class="value">"org.springframework.jdbc.core.JdbcTemplate"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"dataSource"</span> <span class="attribute">ref</span>=<span class="value">"mySqlDataSource"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"transactionManager"</span> <span class="attribute">class</span>=<span class="value">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"dataSource"</span> <span class="attribute">ref</span>=<span class="value">"mySqlDataSource"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　执行单元测试<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">query1</span><span class="params">()</span></span>&#123;</span><br><span class="line">    ApplicationContext ac = <span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="keyword">new</span> String[]&#123;<span class="string">"spring-dynamicDS.xml"</span>&#125;);</span><br><span class="line">    QueryService service = ac.getBean(QueryService.class);</span><br><span class="line">    DynamicDataSource.JdbcContextHolder.setSlave(<span class="string">"slave1"</span>);</span><br><span class="line">    System.out.print(<span class="string">"从库1："</span>);</span><br><span class="line">    service.queryData();</span><br><span class="line">    DynamicDataSource.JdbcContextHolder.setSlave(<span class="string">"slave2"</span>);</span><br><span class="line">    System.out.print(<span class="string">"从库2："</span>);</span><br><span class="line">    service.queryData();</span><br><span class="line">    DynamicDataSource.JdbcContextHolder.setMaster();<span class="comment">//设置主数据源</span></span><br><span class="line">    System.out.print(<span class="string">"主库："</span>);</span><br><span class="line">    service.queryData();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>打印输出<br>从库1：[{id=1, name=loadbalance1数据}]<br>从库2：[{id=1, name=loadbalance2数据}]<br>主库：[{id=1, name=loadbalance3数据}]</p>
<h2 id="u4E0Emybatis_u96C6_u6210"><a href="#u4E0Emybatis_u96C6_u6210" class="headerlink" title="与mybatis集成"></a>与mybatis集成</h2><p>　　在spring与mybatis的集成过程这里不再做介绍，直接贴出配置文件spring-mybatis.xml即可<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource1"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance1"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource2"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance2"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource3"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance3"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="title">util:map</span> <span class="attribute">id</span>=<span class="value">"dataSources"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"1"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource1"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"2"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource2"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"3"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource3"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">util:map</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSourceLookup"</span> <span class="attribute">class</span>=<span class="value">"org.springframework.jdbc.datasource.lookup.MapDataSourceLookup"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">constructor-arg</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="title">ref</span> <span class="attribute">bean</span>=<span class="value">"dataSources"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="title">constructor-arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSourceProxy"</span> <span class="attribute">class</span>=<span class="value">"com.shc.db.loadbalance.datasource.LoadBalanceDataSource"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"defaultTargetDataSource"</span> <span class="attribute">ref</span>=<span class="value">"dataSource1"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"targetDataSources"</span> <span class="attribute">ref</span>=<span class="value">"dataSources"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"dataSourceLookup"</span> <span class="attribute">ref</span>=<span class="value">"dataSourceLookup"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 注意，此时向SqlSessionFactoryBean注入的dataSource为com.shc.db.loadbalance.datasource.LoadBalanceDataSource--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"sqlSessionFactory"</span> <span class="attribute">class</span>=<span class="value">"org.mybatis.spring.SqlSessionFactoryBean"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"dataSource"</span> <span class="attribute">ref</span>=<span class="value">"dataSourceProxy"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"mapperLocations"</span> <span class="attribute">value</span>=<span class="value">"classpath:com/shc/db/loadbalance/mapper/*.xml"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 配置扫描器 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">bean</span> <span class="attribute">class</span>=<span class="value">"org.mybatis.spring.mapper.MapperScannerConfigurer"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"basePackage"</span> <span class="attribute">value</span>=<span class="value">"com.shc.db.loadbalance.mapper"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"sqlSessionFactoryBeanName"</span> <span class="attribute">value</span>=<span class="value">"sqlSessionFactory"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>编写测试代码<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">query1</span><span class="params">()</span></span>&#123;</span><br><span class="line">    ApplicationContext ac = <span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="keyword">new</span> String[]&#123;<span class="string">"spring-mybatis.xml"</span>&#125;);</span><br><span class="line">    TestMapper testMapper = ac.getBean(TestMapper.class);</span><br><span class="line">    List&lt;com.shc.db.loadbalance.model.Test&gt; list = testMapper.listAll();</span><br><span class="line">    System.out.println(list);</span><br><span class="line">    list = testMapper.listAll();</span><br><span class="line">    System.out.println(list);</span><br><span class="line">    list = testMapper.listAll();</span><br><span class="line">    System.out.println(list);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>三次的打印结果分别为：<br>[{id:1, name:loadbalance2数据}]<br>[{id:1, name:loadbalance3数据}]<br>[{id:1, name:loadbalance1数据}]<br>　　到这里我们就完成了spring mybatis中负载均衡的实现。接下来我们假设这样一个需求：多个数据库并非完全一致，此时就需要我们指定某些查询接口采用某个库，另外一些查询接口采用另外的一个库呢，此时该怎么办？根据上面的一行代码：DynamicDataSource.JdbcContextHolder.setSlave(“slave1”);我们可以做到切换到指定的数据库。此时问题来了，我们总不能每次都调用这行代码吧？下面我们将介绍通过注解和aop的方式实现该功能！！</p>
<h2 id="u6CE8_u89E3_u673A_u5236"><a href="#u6CE8_u89E3_u673A_u5236" class="headerlink" title="注解机制"></a>注解机制</h2><p>　　既然采用了注解的模式，首先我们就定义一个注解DataSourceAnno<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@Target</span>(&#123;ElementType.METHOD, ElementType.TYPE&#125;)</span><br><span class="line"><span class="annotation">@Retention</span>(RetentionPolicy.RUNTIME)</span><br><span class="line"><span class="annotation">@Documented</span></span><br><span class="line"><span class="keyword">public</span> <span class="annotation">@interface</span> DataSourceAnno &#123;</span><br><span class="line">    <span class="function">String <span class="title">name</span><span class="params">()</span> <span class="keyword">default</span> DataSourceAnno.master</span>;</span><br><span class="line"></span><br><span class="line">    String master = <span class="string">"master"</span>;</span><br><span class="line">    String slave1 = <span class="string">"slave1"</span>;</span><br><span class="line">    String slave2 = <span class="string">"slave2"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　接着我们定义一个切面，注意，该切面会解析service下所有接口的方法上的注解。并在此处调用代码MybatisOptimizeDataSource.JdbcContextHolder.setJdbcType(data.name());<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//@Aspect</span></span><br><span class="line"><span class="comment">//@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DataSourceAspect</span> </span>&#123;</span><br><span class="line">    <span class="comment">//@Pointcut("execution(* com.shc.db.loadbalance.service.*.*(..))")</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pointCut</span><span class="params">()</span></span>&#123;&#125;;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//  @Before(value = "pointCut()")</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">before</span><span class="params">(JoinPoint point)</span> </span>&#123;</span><br><span class="line">        Object target = point.getTarget();</span><br><span class="line">        <span class="comment">//System.out.println(target.toString());</span></span><br><span class="line">        String method = point.getSignature().getName();</span><br><span class="line">        <span class="comment">//System.out.println(method);</span></span><br><span class="line">        Class&lt;?&gt;[] classz = target.getClass().getInterfaces();</span><br><span class="line">        Class&lt;?&gt;[] parameterTypes = ((MethodSignature) point.getSignature())</span><br><span class="line">                .getMethod().getParameterTypes();</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Method m = classz[<span class="number">0</span>].getMethod(method, parameterTypes);</span><br><span class="line">            <span class="comment">//System.out.println(m.getName());</span></span><br><span class="line">            <span class="keyword">if</span> (m != <span class="keyword">null</span> &amp;&amp; m.isAnnotationPresent(DataSourceAnno.class)) &#123;</span><br><span class="line">                DataSourceAnno data = m.getAnnotation(DataSourceAnno.class);</span><br><span class="line">                MybatisOptimizeDataSource.JdbcContextHolder.setJdbcType(data.name());</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　接下来，就该定义一个spring-mybatis-optimize.xml配置文件了<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line">   <span class="comment">&lt;!--数据库属性配置--&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource1"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance1"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource2"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance2"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSource3"</span> <span class="attribute">class</span>=<span class="value">"com.mchange.v2.c3p0.ComboPooledDataSource"</span> <span class="attribute">destroy-method</span>=<span class="value">"close"</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driverClass"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"jdbcUrl"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://192.168.85.57:3306/loadbalance3"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"user"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="tag">&lt;<span class="title">util:map</span> <span class="attribute">id</span>=<span class="value">"dataSourceMap"</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"master"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource1"</span>/&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"slave1"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource2"</span>/&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">entry</span> <span class="attribute">key</span>=<span class="value">"slave2"</span> <span class="attribute">value-ref</span>=<span class="value">"dataSource3"</span>/&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="title">util:map</span>&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSourceProxy"</span> <span class="attribute">class</span>=<span class="value">"com.shc.db.loadbalance.datasource.MybatisOptimizeDataSource"</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"defaultTargetDataSource"</span> <span class="attribute">ref</span>=<span class="value">"dataSource1"</span>/&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"targetDataSources"</span> <span class="attribute">ref</span>=<span class="value">"dataSourceMap"</span>/&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"sqlSessionFactory"</span> <span class="attribute">class</span>=<span class="value">"org.mybatis.spring.SqlSessionFactoryBean"</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"dataSource"</span> <span class="attribute">ref</span>=<span class="value">"dataSourceProxy"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"mapperLocations"</span> <span class="attribute">value</span>=<span class="value">"classpath:com/shc/db/loadbalance/mapper/*.xml"</span> /&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="comment">&lt;!-- 配置扫描器 --&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="title">bean</span> <span class="attribute">class</span>=<span class="value">"org.mybatis.spring.mapper.MapperScannerConfigurer"</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"basePackage"</span> <span class="attribute">value</span>=<span class="value">"com.shc.db.loadbalance.mapper"</span> /&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"sqlSessionFactoryBeanName"</span> <span class="attribute">value</span>=<span class="value">"sqlSessionFactory"</span> /&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="title">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="comment">&lt;!-- 激活自动代理功能 --&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="title">aop:aspectj-autoproxy</span> <span class="attribute">proxy-target-class</span>=<span class="value">"true"</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="comment">&lt;!-- 配置数据库注解aop --&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="title">bean</span> <span class="attribute">id</span>=<span class="value">"dataSourceAspect"</span> <span class="attribute">class</span>=<span class="value">"com.shc.db.loadbalance.aop.DataSourceAspect"</span> /&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="title">aop:config</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">aop:aspect</span> <span class="attribute">id</span>=<span class="value">"c"</span> <span class="attribute">ref</span>=<span class="value">"dataSourceAspect"</span> <span class="attribute">order</span>=<span class="value">"1"</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="title">aop:pointcut</span> <span class="attribute">id</span>=<span class="value">"tx"</span> <span class="attribute">expression</span>=<span class="value">"execution(* com.shc.db.loadbalance.service..*.*(..))"</span>/&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="title">aop:before</span> <span class="attribute">pointcut-ref</span>=<span class="value">"tx"</span> <span class="attribute">method</span>=<span class="value">"before"</span>/&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="title">aop:aspect</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="title">aop:config</span>&gt;</span></span><br><span class="line">   <span class="comment">&lt;!--&lt;aop:config&gt;</span><br><span class="line">       &lt;aop:pointcut id="service" expression="execution(* com.datasource..*.service.*.*(..))"/&gt;</span><br><span class="line">       &amp;lt;!&amp;ndash; 关键配置，切换数据源一定要比持久层代码更先执行（事务也算持久层代码） &amp;ndash;&amp;gt;</span><br><span class="line">       &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="service" order="2"/&gt;</span><br><span class="line">       &lt;aop:advisor advice-ref="dataSourceExchange" pointcut-ref="service" order="1"/&gt;</span><br><span class="line">   &lt;/aop:config&gt;--&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 配置数据库注解aop --&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　最后，我们在接口IQueryService上增加三个方法<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@DataSourceAnno</span>(name = DataSourceAnno.master)</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">mybatisOptimize1</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="annotation">@DataSourceAnno</span>(name = DataSourceAnno.slave1)</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">mybatisOptimize2</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="annotation">@DataSourceAnno</span>(name = DataSourceAnno.slave2)</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">mybatisOptimize3</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure></p>
<p>　　加入单元代码<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">query2</span><span class="params">()</span></span>&#123;</span><br><span class="line">    ApplicationContext ac = <span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="keyword">new</span> String[]&#123;<span class="string">"spring-mybatis-optimize.xml"</span>&#125;);</span><br><span class="line">    QueryServiceImpl service = ac.getBean(QueryServiceImpl.class);</span><br><span class="line">    service.mybatisOptimize1();</span><br><span class="line">    service.mybatisOptimize2();</span><br><span class="line">    service.mybatisOptimize3();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　执行结果如下：<br>[{id:1, name:loadbalance1数据}]<br>[{id:1, name:loadbalance2数据}]<br>[{id:1, name:loadbalance3数据}]<br>　　到此就大功告成了。额外介绍一点，mysql驱动自带的replicationDriver来实现，可以考虑一下。本文示例代码下载地址：<a href="/code/db-loadbalance.rar">db-loadbalance.rar</a>。最后附上一张网络图片：<img src="/images/multi-datasource.jpg" alt="multi-datasource.jpg"></p>
<h2 id="u53C2_u8003_u8D44_u6599"><a href="#u53C2_u8003_u8D44_u6599" class="headerlink" title="参考资料"></a>参考资料</h2><p><a href="http://blog.csdn.net/keda8997110/article/details/16827215" target="_blank" rel="external">http://blog.csdn.net/keda8997110/article/details/16827215</a><br><a href="http://blog.csdn.net/huoyunshen88/article/details/36674861" target="_blank" rel="external">http://blog.csdn.net/huoyunshen88/article/details/36674861</a><br><a href="http://www.cnblogs.com/davidwang456/p/4318303.html" target="_blank" rel="external">http://www.cnblogs.com/davidwang456/p/4318303.html</a><br><a href="http://blog.csdn.net/lixiucheng005/article/details/17391857" target="_blank" rel="external">http://blog.csdn.net/lixiucheng005/article/details/17391857</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/09/mybatis/9.Mybatis系列之负载均衡与读写分离/" data-id="cijzzpv8j00721cfsfynfi8a7" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mybatis/">mybatis</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/spring/">spring</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-mybatis/8.Mybatis系列之Association" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/09/mybatis/8.Mybatis系列之Association/" class="article-date">
  <time datetime="2015-12-09T10:00:00.000Z" itemprop="datePublished">2015-12-09</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/mybatis/">mybatis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/09/mybatis/8.Mybatis系列之Association/">Mybatis系列八之Association</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　<br><a href="/code/mybatis.zip">mybatis.zip</a></p>
<h2 id="u53C2_u8003_u6587_u7AE0"><a href="#u53C2_u8003_u6587_u7AE0" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="http://blog.csdn.net/isea533/article/details/20868189" target="_blank" rel="external">http://blog.csdn.net/isea533/article/details/20868189</a><br><a href="http://blog.csdn.net/xiaoyu411502/article/details/45621603" target="_blank" rel="external">http://blog.csdn.net/xiaoyu411502/article/details/45621603</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/09/mybatis/8.Mybatis系列之Association/" data-id="cijzzpv8o00781cfs4pye5yb7" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mybatis/">mybatis</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/spring/">spring</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-mybatis/7.Mybatis系列之maven generator插件" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/09/mybatis/7.Mybatis系列之maven generator插件/" class="article-date">
  <time datetime="2015-12-09T10:00:00.000Z" itemprop="datePublished">2015-12-09</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/mybatis/">mybatis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/09/mybatis/7.Mybatis系列之maven generator插件/">Mybatis系列七之generator插件</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　mybatis是目前大家普遍采用的DAO框架，在此时的开发过程中，需要编写mapper.xml等文件，极为繁琐，还容易出现错误。其实有一个非常方便的maven插件：mybatis generator。它可以根据数据库表结构，自动生成mybatis代码和配置文件，方便大家使用。这里便不再做详细介绍，可以参考<a href="http://www.cnblogs.com/smileberry/p/4145872.html" title="mybatis generator插件使用" target="_blank" rel="external">mybatis generator插件使用</a>。当然实际的使用过程中，generator肯定有不少不尽人意的地方，好在他提供了插件的机制，方便我们做扩展。</p>
<p>这里讲解的插件开发依赖以下mybatis版本：</p>
<p><a href="/code/mybatis.zip">mybatis.zip</a></p>
<h2 id="u53C2_u8003_u6587_u7AE0"><a href="#u53C2_u8003_u6587_u7AE0" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="http://www.tuicool.com/articles/fiuqUny" target="_blank" rel="external">http://www.tuicool.com/articles/fiuqUny</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/09/mybatis/7.Mybatis系列之maven generator插件/" data-id="cijzzpv8r007c1cfsey006mgc" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mybatis/">mybatis</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/spring/">spring</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-mybatis/6.Mybatis系列之Spring集成" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/09/mybatis/6.Mybatis系列之Spring集成/" class="article-date">
  <time datetime="2015-12-09T09:00:00.000Z" itemprop="datePublished">2015-12-09</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/mybatis/">mybatis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/09/mybatis/6.Mybatis系列之Spring集成/">Mybatis系列六之Spring集成</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　本篇文章不再介绍spring-mybatis的使用方式，而是深入的源码进行分析，同时之前几篇文中中提到的mybatis-conf.xml配置文件进行比较。</p>
<p><a href="/code/mybatis.zip">mybatis.zip</a></p>
<h2 id="u53C2_u8003_u6587_u7AE0"><a href="#u53C2_u8003_u6587_u7AE0" class="headerlink" title="参考文章"></a>参考文章</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/09/mybatis/6.Mybatis系列之Spring集成/" data-id="cijzzpv8u007g1cfsk8s3e3aw" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mybatis/">mybatis</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/spring/">spring</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-mybatis/5.Mybatis系列之动态SQL" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/09/mybatis/5.Mybatis系列之动态SQL/" class="article-date">
  <time datetime="2015-12-09T08:00:00.000Z" itemprop="datePublished">2015-12-09</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/mybatis/">mybatis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/09/mybatis/5.Mybatis系列之动态SQL/">Mybatis系列五之动态SQL</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　传统的使用JDBC的方法，相信大家在组合复杂的的SQL语句的时候，需要去拼接，稍不注意哪怕少了个空格，都会导致错误。Mybatis的动态SQL功能正是为了解决这种问题， 其通过 if, choose, when, otherwise, trim, where, set, foreach标签，可组合成非常灵活的SQL语句，从而提高开发人员的效率。下面就去感受Mybatis动态SQL的魅力吧：</p>
<h2 id="if"><a href="#if" class="headerlink" title="if"></a>if</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">select</span> <span class="attribute">id</span>=<span class="value">"findUserById"</span> <span class="attribute">resultType</span>=<span class="value">"user"</span>&gt;</span></span><br><span class="line">       select * from user where</span><br><span class="line">       <span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"id != null"</span>&gt;</span></span><br><span class="line">           id=#&#123;id&#125;</span><br><span class="line">       <span class="tag">&lt;/<span class="title">if</span>&gt;</span></span><br><span class="line">       and deleteFlag=0;</span><br><span class="line"><span class="tag">&lt;/<span class="title">select</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>　　上面例子中，如果传入的id不为空， 那么才会SQL才拼接id = #{id}。但是此时会出现一个问题：要是传入的id为null，那么最终的SQL语句成为：select * from user where and deleteFlag=0。这语句是有问题的，这时就需要用到mybatis的 where 标签了</p>
<h2 id="where"><a href="#where" class="headerlink" title="where"></a>where</h2><p>　　将上面的例子进行简单的改造<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">select</span> <span class="attribute">id</span>=<span class="value">"findUserById"</span> <span class="attribute">resultType</span>=<span class="value">"user"</span>&gt;</span></span><br><span class="line">       select * from user where</span><br><span class="line">	<span class="tag">&lt;<span class="title">where</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"id != null"</span>&gt;</span></span><br><span class="line">               id=#&#123;id&#125;</span><br><span class="line">           <span class="tag">&lt;/<span class="title">if</span>&gt;</span></span><br><span class="line">           and deleteFlag=0;</span><br><span class="line">	<span class="tag">&lt;/<span class="title">where</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">select</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　此时，mybatis对它做了处理，当它遇到AND或者OR这些，它知道怎么处理。其实我们可以通过 trim 标签去自定义这种处理规则。</p>
<h2 id="trim"><a href="#trim" class="headerlink" title="trim"></a>trim</h2><p>上面的where标签，其实用trim可以表示如下：<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">trim</span> <span class="attribute">prefix</span>=<span class="value">"WHERE"</span> <span class="attribute">prefixOverrides</span>=<span class="value">"AND |OR "</span>&gt;</span></span><br><span class="line">  ... </span><br><span class="line"><span class="tag">&lt;/<span class="title">trim</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　它的意思就是： 当WHERE后紧随AND或则OR的时候，就去除AND或者OR。 除了WHERE以外， 其实还有一个比较经典的实现，那就是SET。</p>
<h2 id="set"><a href="#set" class="headerlink" title="set"></a>set</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">update</span> <span class="attribute">id</span>=<span class="value">"updateUser"</span> <span class="attribute">parameterType</span>=<span class="value">"com.dy.entity.User"</span>&gt;</span></span><br><span class="line">	update user set </span><br><span class="line">		<span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"name != null"</span>&gt;</span></span><br><span class="line">			name = #&#123;name&#125;,</span><br><span class="line">		<span class="tag">&lt;/<span class="title">if</span>&gt;</span> </span><br><span class="line">		<span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"password != null"</span>&gt;</span></span><br><span class="line">			password = #&#123;password&#125;,</span><br><span class="line">		<span class="tag">&lt;/<span class="title">if</span>&gt;</span> </span><br><span class="line">		<span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"age != null"</span>&gt;</span></span><br><span class="line">			age = #&#123;age&#125;</span><br><span class="line">		<span class="tag">&lt;/<span class="title">if</span>&gt;</span> </span><br><span class="line">		<span class="tag">&lt;<span class="title">where</span>&gt;</span></span><br><span class="line">			<span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"id != null"</span>&gt;</span></span><br><span class="line">				id = #&#123;id&#125;</span><br><span class="line">			<span class="tag">&lt;/<span class="title">if</span>&gt;</span></span><br><span class="line">			and deleteFlag = 0;</span><br><span class="line">		<span class="tag">&lt;/<span class="title">where</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">update</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>　　此时，新的问题产生了：如果只有name不为null，那么这SQL就成了 update set name = #{name}, where …，name后面那逗号会导致出。这时候，就可以用mybatis为我们提供的set标签了。<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">update</span> <span class="attribute">id</span>=<span class="value">"updateUser"</span> <span class="attribute">parameterType</span>=<span class="value">"com.dy.entity.User"</span>&gt;</span></span><br><span class="line">	update user</span><br><span class="line">	<span class="tag">&lt;<span class="title">set</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"name != null"</span>&gt;</span>name = #&#123;name&#125;,<span class="tag">&lt;/<span class="title">if</span>&gt;</span> </span><br><span class="line">		<span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"password != null"</span>&gt;</span>password = #&#123;password&#125;,<span class="tag">&lt;/<span class="title">if</span>&gt;</span> </span><br><span class="line">		<span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"age != null"</span>&gt;</span>age = #&#123;age&#125;,<span class="tag">&lt;/<span class="title">if</span>&gt;</span> </span><br><span class="line">	<span class="tag">&lt;/<span class="title">set</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="title">where</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="title">if</span> <span class="attribute">test</span>=<span class="value">"id != null"</span>&gt;</span></span><br><span class="line">			id = #&#123;id&#125;</span><br><span class="line">		<span class="tag">&lt;/<span class="title">if</span>&gt;</span></span><br><span class="line">		and deleteFlag = 0;</span><br><span class="line">	<span class="tag">&lt;/<span class="title">where</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">update</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　这个用trim 可表示为：<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">trim</span> <span class="attribute">prefix</span>=<span class="value">"SET"</span> <span class="attribute">suffixOverrides</span>=<span class="value">","</span>&gt;</span></span><br><span class="line">  ...</span><br><span class="line"><span class="tag">&lt;/<span class="title">trim</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　WHERE是使用的prefixOverrides（前缀），SET是使用的suffixOverrides（后缀）！</p>
<h2 id="foreach"><a href="#foreach" class="headerlink" title="foreach"></a>foreach</h2><p>　　java中有for循环，同样，mybatis中有foreach，可通过它实现循环，循环的对象当然主要是java容器和数组。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">select</span> <span class="attribute">id</span>=<span class="value">"selectPostIn"</span> <span class="attribute">resultType</span>=<span class="value">"domain.blog.Post"</span>&gt;</span></span><br><span class="line">  SELECT *</span><br><span class="line">  FROM POST P</span><br><span class="line">  WHERE ID in</span><br><span class="line">  <span class="tag">&lt;<span class="title">foreach</span> <span class="attribute">item</span>=<span class="value">"item"</span> <span class="attribute">index</span>=<span class="value">"index"</span> <span class="attribute">collection</span>=<span class="value">"list"</span></span><br><span class="line">      <span class="attribute">open</span>=<span class="value">"("</span> <span class="attribute">separator</span>=<span class="value">","</span> <span class="attribute">close</span>=<span class="value">")"</span>&gt;</span></span><br><span class="line">        #&#123;item&#125;</span><br><span class="line">  <span class="tag">&lt;/<span class="title">foreach</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">select</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h2 id="choose"><a href="#choose" class="headerlink" title="choose"></a>choose</h2><p>　　Java中有switch,  mybatis有choose。<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">select</span> <span class="attribute">id</span>=<span class="value">"findActiveBlogLike"</span></span><br><span class="line">     <span class="attribute">resultType</span>=<span class="value">"Blog"</span>&gt;</span></span><br><span class="line">  SELECT * FROM BLOG WHERE state = ‘ACTIVE’</span><br><span class="line">  <span class="tag">&lt;<span class="title">choose</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">when</span> <span class="attribute">test</span>=<span class="value">"title != null"</span>&gt;</span></span><br><span class="line">      AND title like #&#123;title&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="title">when</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">when</span> <span class="attribute">test</span>=<span class="value">"author != null and author.name != null"</span>&gt;</span></span><br><span class="line">      AND author_name like #&#123;author.name&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="title">when</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">otherwise</span>&gt;</span></span><br><span class="line">      AND featured = 1</span><br><span class="line">    <span class="tag">&lt;/<span class="title">otherwise</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="title">choose</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">select</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　以上例子中： 当title和author都不为null的时候， 那么选择二选一（前者优先）， 如果都为null, 那么就选择 otherwise中的， 如果tilte和author只有一个不为null, 那么就选择不为null的那个。<br>　　本文只是根据网上资料直接移植过来，实际工作中只需要多试试就行了</p>
<h2 id="u53C2_u8003_u6587_u7AE0"><a href="#u53C2_u8003_u6587_u7AE0" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="http://www.cnblogs.com/dongying/p/4092662.html" target="_blank" rel="external">http://www.cnblogs.com/dongying/p/4092662.html</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/09/mybatis/5.Mybatis系列之动态SQL/" data-id="cijzzpv8x007k1cfs32p5urcb" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/java/">java</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mybatis/">mybatis</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-mybatis/4.Mybatis系列之Plugin" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/09/mybatis/4.Mybatis系列之Plugin/" class="article-date">
  <time datetime="2015-12-09T07:00:00.000Z" itemprop="datePublished">2015-12-09</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/mybatis/">mybatis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/09/mybatis/4.Mybatis系列之Plugin/">Mybatis系列四之Plugin</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　在mybatis中提供了较为完整的plugin机制，它其实就是个interceptor，可以拦截Executor、ParameterHandler、ResultSetHandler、StatementHandler的部分方法，处理我们自己的逻辑，如分页、sql日志等。<br>　　Executor就是真正执行sql语句的类，具体的实现包括BaseExecutor、BathExecutor、CachingExecutor、ReuseExecutor、SimpleExecutor等。Mybatis在创建Executor对象时会执行代码：executor =(Executor) interceptorChain.pluginAll(executor); 此时下面示例ExamplePlugin类的plugin方法会被调用生成代理。<br>　　ParameterHandler是处理传入参数的，具体的执行则是由实现类DefaultParameterHandler完成。该实现类也仅仅是包装了TypeHandlerRegistry、BoundSql等关键信息。其中TypeHandlerRegistry用于处理java -&gt; db的数据类型转换。BoundSql则包含了执行性的sql、参数等信息。<br>　　ResultSetHandler则用于处理返回结果，大多数情况下都是将查询结果转换成java bean，具体的执行则是由实现类DefaultResultSetHandler完成。与DefaultParameterHandler一样，它也仅仅是封装了TypeHandlerRegistry、ObjectFactory（生成实体类）和ResultHandler等关键信息。<br>　　StatementHandler则是承担java.sql.Statement的工作，其实现主要包括BaseStatementHandler、CallableStatementHandler、PreparedStatementHandler、SimpleStatementHandler和RoutingStatementHandler。其中RoutingStatementHandler类如其名，主要用于路由到CallableStatementHandler、PreparedStatementHandler等。BaseStatementHandler则完成一个公共的初始化工作，如初始化java.sql.Statement的工作。<br>　　下面我们通过一个具体的实现，开始plugin之旅！</p>
<h2 id="u5B9A_u4E49ExamplePlugin"><a href="#u5B9A_u4E49ExamplePlugin" class="headerlink" title="定义ExamplePlugin"></a>定义ExamplePlugin</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@Intercepts</span>(&#123;</span><br><span class="line">        <span class="annotation">@Signature</span>(</span><br><span class="line">                type = Executor.class,</span><br><span class="line">                method =<span class="string">"update"</span>,</span><br><span class="line">                args = &#123;MappedStatement.class, Object.class&#125;),</span><br><span class="line">        <span class="annotation">@Signature</span>(</span><br><span class="line">                type = Executor.class,</span><br><span class="line">                method =<span class="string">"query"</span>,</span><br><span class="line">                args = &#123;MappedStatement.class, Object.class,RowBounds.class, ResultHandler.class&#125;)&#125;)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ExamplePlugin</span> <span class="keyword">implements</span> <span class="title">Interceptor</span> </span>&#123;</span><br><span class="line">    Properties properties;</span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">intercept</span><span class="params">(Invocation invocation)</span> <span class="keyword">throws</span> Throwable </span>&#123;</span><br><span class="line">        String logInfo = properties.getProperty(<span class="string">"logInfo"</span>);</span><br><span class="line">        System.out.println(logInfo);</span><br><span class="line">        <span class="keyword">return</span> invocation.proceed();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">plugin</span><span class="params">(Object target)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> Plugin.wrap(target, <span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setProperties</span><span class="params">(Properties properties)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.properties = properties;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>　　从上面我们可以看出，通过注解Intercepts指定需要拦截的类的方法，这里我们可以配置多个。intercept方法则是执行拦截的操作，我们可以在里面添加额外的业务逻辑。plugin方法则用于生成代理类。<strong>进入Plugin.wrap可以看到Mybatis采用的是java的动态代理实现的插件机制</strong>。接着，我们在mybatis-conf.xml中配置该插件。<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">plugins</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="title">plugin</span> <span class="attribute">interceptor</span>=<span class="value">"com.openim.test.mybatis.plugins.ExamplePlugin"</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"logInfo"</span> <span class="attribute">value</span>=<span class="value">"插件被调用了！！！"</span>/&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="title">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">plugins</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　运行前面章节的示例代码，可以看到日志被打印了。该插件将会了Executor类的update和quer方法被执行时调用！！</p>
<h2 id="u5206_u9875_u63D2_u4EF6"><a href="#u5206_u9875_u63D2_u4EF6" class="headerlink" title="分页插件"></a>分页插件</h2><p>　　在mybatis中，最常用的插件可能就是分页插件了，目前比较完善的分页插件为PageHelper，git地址为：<a href="http://git.oschina.net/free/Mybatis_PageHelper/tree/master" title="PageHelper" target="_blank" rel="external">PageHelper</a>。作者在项目的wiki中指出：在需要进行分页的Mybatis方法前调用PageHelper.startPage静态方法即可，紧跟在这个方法后的第一个Mybatis查询方法会被进行分页，详见：<a href="http://git.oschina.net/free/Mybatis_PageHelper/blob/master/wikis/HowToUse.markdown" title="HowToUse" target="_blank" rel="external">HowToUse</a>。<br>　　那么此时问题来了，在并发请求的情况下，多线程同时访问，如何保证程序执行的正确性呢？（两个线程都执行了PageHelper.startPage，还没来得及执行后面的查询语句）！实际上，在PageHelper.startPage方法中，会调用SqlUtil.setLocalPage(page)，此时传入参数会放入 <strong>ThreadLocal</strong> 中，这样就很简单的解决了多线程同时请求访问时的隔离问题<br>　　该插件还采用了jsqlparser工具包，用于解析sql，并生成分页语句。下面我们将简单介绍一下。</p>
<h2 id="jsqlparser"><a href="#jsqlparser" class="headerlink" title="jsqlparser"></a>jsqlparser</h2><p>　　本文示例代码下载地址：<a href="/code/mybatis2.zip">mybatis2.zip</a></p>
<h2 id="u53C2_u8003_u6587_u7AE0"><a href="#u53C2_u8003_u6587_u7AE0" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="http://blog.csdn.net/hupanfeng/article/details/9247379" target="_blank" rel="external">http://blog.csdn.net/hupanfeng/article/details/9247379</a><br><a href="http://www.oschina.net/code/snippet_1018034_26673（打印sql，并显示执行的时间）" target="_blank" rel="external">http://www.oschina.net/code/snippet_1018034_26673（打印sql，并显示执行的时间）</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/09/mybatis/4.Mybatis系列之Plugin/" data-id="cijzzpv91007o1cfsdnq4emj5" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/java/">java</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mybatis/">mybatis</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-mybatis/3.Mybatis系列之自定义TypeHandler" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/09/mybatis/3.Mybatis系列之自定义TypeHandler/" class="article-date">
  <time datetime="2015-12-09T06:00:00.000Z" itemprop="datePublished">2015-12-09</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/mybatis/">mybatis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/09/mybatis/3.Mybatis系列之自定义TypeHandler/">Mybatis系列三之自定义TypeHandler</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　在这篇文章中，我们将分析mybatis的TypHandler实现原理，并且自定义一个用于解析json的JsonTypeHandler.</p>
<h2 id="TypeHandler_u914D_u7F6E"><a href="#TypeHandler_u914D_u7F6E" class="headerlink" title="TypeHandler配置"></a>TypeHandler配置</h2><p>　　在一个完整的orm框架中，基本上都需要实现这样一个功能（包括apache dbutils在内）：无论是在预处理语句（PreparedStatement）中设置一个参数时，还是从结果集中取出一个值时，都需要用类型处理器将获取的值以合适的方式转换成 Java（或者数据库） 类型，这样就可以实现数据库类型和java类型的自动转换。下面看看mybatis中对typeHanderl节点的解析入口：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">typeHandlerElement</span><span class="params">(XNode parent)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (parent != <span class="keyword">null</span>) &#123;</span><br><span class="line">    <span class="keyword">for</span> (XNode child : parent.getChildren()) &#123;</span><br><span class="line">      <span class="comment">//如果子节点为package,则扫描该包下的所有类并注册到TypeHandlerRegistry中</span></span><br><span class="line">      <span class="keyword">if</span> (<span class="string">"package"</span>.equals(child.getName())) &#123;</span><br><span class="line">        String typeHandlerPackage = child.getStringAttribute(<span class="string">"name"</span>);</span><br><span class="line">        typeHandlerRegistry.register(typeHandlerPackage);</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">//否则获取子节点的属性javaType、jdbcType和handler</span></span><br><span class="line">        String javaTypeName = child.getStringAttribute(<span class="string">"javaType"</span>);</span><br><span class="line">        String jdbcTypeName = child.getStringAttribute(<span class="string">"jdbcType"</span>);</span><br><span class="line">        String handlerTypeName = child.getStringAttribute(<span class="string">"handler"</span>);</span><br><span class="line">        <span class="comment">//注册到TypeHandlerRegistry中</span></span><br><span class="line">        Class&lt;?&gt; javaTypeClass = resolveClass(javaTypeName);</span><br><span class="line">        JdbcType jdbcType = resolveJdbcType(jdbcTypeName);</span><br><span class="line">        Class&lt;?&gt; typeHandlerClass = resolveClass(handlerTypeName);</span><br><span class="line">        <span class="keyword">if</span> (javaTypeClass != <span class="keyword">null</span>) &#123;</span><br><span class="line">          <span class="keyword">if</span> (jdbcType == <span class="keyword">null</span>) &#123;</span><br><span class="line">            typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          typeHandlerRegistry.register(typeHandlerClass);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　事实上，在TypeHandlerRegistry类的构造方法中，我们可以看到，mybatis已经实现了很多的TypeHandler，用于解析不同的数据类型<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">TypeHandlerRegistry</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  register(Boolean.class, <span class="keyword">new</span> BooleanTypeHandler());</span><br><span class="line">  register(<span class="keyword">boolean</span>.class, <span class="keyword">new</span> BooleanTypeHandler());</span><br><span class="line">  register(JdbcType.BOOLEAN, <span class="keyword">new</span> BooleanTypeHandler());</span><br><span class="line">  register(JdbcType.BIT, <span class="keyword">new</span> BooleanTypeHandler());</span><br><span class="line"></span><br><span class="line">  register(Byte.class, <span class="keyword">new</span> ByteTypeHandler());</span><br><span class="line">  register(<span class="keyword">byte</span>.class, <span class="keyword">new</span> ByteTypeHandler());</span><br><span class="line">  register(JdbcType.TINYINT, <span class="keyword">new</span> ByteTypeHandler());</span><br><span class="line"></span><br><span class="line">  register(Short.class, <span class="keyword">new</span> ShortTypeHandler());</span><br><span class="line">  register(<span class="keyword">short</span>.class, <span class="keyword">new</span> ShortTypeHandler());</span><br><span class="line">  register(JdbcType.SMALLINT, <span class="keyword">new</span> ShortTypeHandler());</span><br><span class="line"></span><br><span class="line">  register(Integer.class, <span class="keyword">new</span> IntegerTypeHandler());</span><br><span class="line">  register(<span class="keyword">int</span>.class, <span class="keyword">new</span> IntegerTypeHandler());</span><br><span class="line">  register(JdbcType.INTEGER, <span class="keyword">new</span> IntegerTypeHandler());</span><br><span class="line"></span><br><span class="line">  ......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　现在有这样的一个需求，在数据库中需要存储特定格式的数据，如存成json的格式。同时读取数据时，能够自动的转换成相应的对象。此时，有两种方案可以解决，第一种是在程序中进行转换，再存入数据库，或者是通过自定义的TypeHandler，实现json格式的数据自动存取功能。这里我们采用第二种方式。<br>　　下面实现这样的一个功能：<em>Address</em> 类包含两个属性country和province。并将 <em>Address</em> 类作为 <em>User</em> 类的一个属性。在插入数据时，address属性保存成json格式，读取数据时，将json数据自动转成Address对象。<br>　　首先，定义一个JsonTypeHandler，实现如下（注意，这里采用的阿里的fastjson，请自行在pom文件中添加相应依赖）：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JsonTypeHandler</span> <span class="keyword">extends</span> <span class="title">BaseTypeHandler</span>&lt;<span class="title">Address</span>&gt; </span>&#123;</span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setNonNullParameter</span><span class="params">(PreparedStatement ps, <span class="keyword">int</span> i, Address parameter,</span><br><span class="line">                                    JdbcType jdbcType)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        ps.setString(i, JSONObject.toJSONString(parameter));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Address <span class="title">getNullableResult</span><span class="params">(ResultSet rs, String columnName)</span></span><br><span class="line">            <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> JSON.parseObject(rs.getString(columnName), Address.class);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Address <span class="title">getNullableResult</span><span class="params">(ResultSet rs, <span class="keyword">int</span> columnIndex)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> JSON.parseObject(rs.getString(columnIndex), Address.class);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Address <span class="title">getNullableResult</span><span class="params">(CallableStatement cs, <span class="keyword">int</span> columnIndex)</span></span><br><span class="line">            <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> JSON.parseObject(cs.getString(columnIndex), Address.class);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　接着，新建一个Address类<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Address</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String country;</span><br><span class="line">    <span class="keyword">private</span> String province;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Address</span><span class="params">()</span></span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Address</span><span class="params">(String country, String province)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.country = country;</span><br><span class="line">        <span class="keyword">this</span>.province = province;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getCountry</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> country;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setCountry</span><span class="params">(String country)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.country = country;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getProvince</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> province;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setProvince</span><span class="params">(String province)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.province = province;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="annotation">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> country + <span class="string">" "</span> + province;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　接着在mybatis-conf.xml中，增加节点<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">typeHandlers</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">typeHandler</span> <span class="attribute">handler</span>=<span class="value">"com.openim.test.mybatis.handler.JsonTypeHandler"</span></span><br><span class="line">                     <span class="attribute">javaType</span>=<span class="value">"com.openim.test.mybatis.model.Address"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">typeHandlers</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　最后增加测试方法<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run3</span><span class="params">()</span></span>&#123;</span><br><span class="line"></span><br><span class="line">    String resource = <span class="string">"mybatis-conf.xml"</span>;</span><br><span class="line">    InputStream is = Test1.class.getClassLoader().getResourceAsStream(resource);</span><br><span class="line">    SqlSessionFactory sessionFactory = <span class="keyword">new</span> SqlSessionFactoryBuilder().build(is);</span><br><span class="line"></span><br><span class="line">    SqlSession session = sessionFactory.openSession();</span><br><span class="line">    </span><br><span class="line">    User user = <span class="keyword">new</span> User();</span><br><span class="line">    user.setId(<span class="number">4</span>);</span><br><span class="line">    user.setAge(<span class="number">18</span>);</span><br><span class="line">    user.setName(<span class="string">"明月2"</span>);</span><br><span class="line">    user.setAddress(<span class="keyword">new</span> Address(<span class="string">"中国"</span>, <span class="string">"北京"</span>));</span><br><span class="line"></span><br><span class="line">    Integer count = session.getMapper(UserMapper.class).insertWithAddress(user);</span><br><span class="line">    session.commit();</span><br><span class="line">    System.out.println(count);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　运行即可看到想要的结果。实际上，在实现的过程中，遇到了可以存成json格式数据，但是读取不到的问题！通过调试进入mybatis的源码，一步步跟踪解决。需要耐心即可！！！下面给出源码链接<br><a href="/code/mybatis.zip">mybatis.zip</a></p>
<h2 id="u53C2_u8003_u6587_u7AE0"><a href="#u53C2_u8003_u6587_u7AE0" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="http://blog.csdn.net/xiaoyu411502/article/details/45622511" target="_blank" rel="external">http://blog.csdn.net/xiaoyu411502/article/details/45622511</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/09/mybatis/3.Mybatis系列之自定义TypeHandler/" data-id="cijzzpv94007s1cfskulexbbk" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/java/">java</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mybatis/">mybatis</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-mybatis/2.Mybatis系列之配置解析" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2015/12/09/mybatis/2.Mybatis系列之配置解析/" class="article-date">
  <time datetime="2015-12-09T05:00:00.000Z" itemprop="datePublished">2015-12-09</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/mybatis/">mybatis</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2015/12/09/mybatis/2.Mybatis系列之配置解析/">Mybatis系列二之配置解析</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="u6982_u8FF0"><a href="#u6982_u8FF0" class="headerlink" title="概述"></a>概述</h2><p>　　在上一篇文章《》中，我们新建了一个mybatis-conf.xml配置文件，该配置文件包含了mybatis所有的可配置项，那么在mybatis中，有哪些可以配置项呢。它们的如何进行解析和工作的呢！下面我将带领大家一一介绍</p>
<h2 id="u89E3_u6790_u5165_u53E3"><a href="#u89E3_u6790_u5165_u53E3" class="headerlink" title="解析入口"></a>解析入口</h2><p>　　从测试代码中，我们可以发现，mybatis-conf.xml配置文件的解析入口由SqlSessionFactoryBuilder的build()方法开始，下面展示build()方法中关键的两行代码：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">XMLConfigBuilder parser = <span class="keyword">new</span> XMLConfigBuilder(inputStream, environment, properties);</span><br><span class="line"><span class="keyword">return</span> build(parser.parse());</span><br></pre></td></tr></table></figure></p>
<p>　　从上面的代码可以发现，整个配置文件的解析工作由XMLConfigBuilder类完成，调用其parse()方法后，配置信息被解析成Configuration类。实际上配置文件中各节点的解析工作由XMLConfigBuilder类中的parseConfiguration方法完成。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parseConfiguration</span><span class="params">(XNode root)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="comment">//issue #117 read properties first</span></span><br><span class="line">    propertiesElement(root.evalNode(<span class="string">"properties"</span>));</span><br><span class="line">    typeAliasesElement(root.evalNode(<span class="string">"typeAliases"</span>));</span><br><span class="line">    pluginElement(root.evalNode(<span class="string">"plugins"</span>));</span><br><span class="line">    objectFactoryElement(root.evalNode(<span class="string">"objectFactory"</span>));</span><br><span class="line">    objectWrapperFactoryElement(root.evalNode(<span class="string">"objectWrapperFactory"</span>));</span><br><span class="line">    reflectionFactoryElement(root.evalNode(<span class="string">"reflectionFactory"</span>));</span><br><span class="line">    settingsElement(root.evalNode(<span class="string">"settings"</span>));</span><br><span class="line">    <span class="comment">// read it after objectFactory and objectWrapperFactory issue #631</span></span><br><span class="line">    environmentsElement(root.evalNode(<span class="string">"environments"</span>));</span><br><span class="line">    databaseIdProviderElement(root.evalNode(<span class="string">"databaseIdProvider"</span>));</span><br><span class="line">    typeHandlerElement(root.evalNode(<span class="string">"typeHandlers"</span>));</span><br><span class="line">    mapperElement(root.evalNode(<span class="string">"mappers"</span>));</span><br><span class="line">  &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> BuilderException(<span class="string">"Error parsing SQL Mapper Configuration. Cause: "</span> + e, e);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　通过代码分析，我们可以发现：<br>　　1. configuration节点为根节点。<br>　　2. 在configuration节点之下，我们可以配置的节点， 分别为：properties、typeAliases、plugins、objectFactory、objectWrapperFactory、reflectionFactory、settings、environments、databaseIdProvider、typeHandlers、mappers。<br>　　下面，我们开始逐步介绍以上几个配置节点</p>
<h2 id="properties_u914D_u7F6E"><a href="#properties_u914D_u7F6E" class="headerlink" title="properties配置"></a>properties配置</h2><p>　　在properties节点的配置中，有以下几种方式进行配置<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 方法一： 从外部指定properties配置文件, 除了使用resource属性指定外，还可通过url属性指定url --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">properties</span> <span class="attribute">resource</span>=<span class="value">"dbConfig.properties"</span>&gt;</span><span class="tag">&lt;/<span class="title">properties</span>&gt;</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 方法二： 直接配置为xml --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="title">properties</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driver"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"url"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://localhost:3306/test1"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"username"</span> <span class="attribute">value</span>=<span class="value">"root"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"root"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">properties</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　事实上，以上几种配置方式可以通过properties的解析源码分析得到。通过下面的源码，我们可以发现，xml中的配置属性会被配置文件中配置的数据覆盖<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">propertiesElement</span><span class="params">(XNode context)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (context != <span class="keyword">null</span>) &#123;</span><br><span class="line">    <span class="comment">//解析properties节点下的子节点，子节点名称任意，只需要还有属性name和value即可</span></span><br><span class="line">    Properties defaults = context.getChildrenAsProperties();</span><br><span class="line">    <span class="comment">//解析properties节点的属性resource或url</span></span><br><span class="line">    String resource = context.getStringAttribute(<span class="string">"resource"</span>);</span><br><span class="line">    String url = context.getStringAttribute(<span class="string">"url"</span>);</span><br><span class="line">    <span class="keyword">if</span> (resource != <span class="keyword">null</span> &amp;&amp; url != <span class="keyword">null</span>) &#123;</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> BuilderException(<span class="string">"The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other."</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (resource != <span class="keyword">null</span>) &#123;</span><br><span class="line">      defaults.putAll(Resources.getResourceAsProperties(resource));</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (url != <span class="keyword">null</span>) &#123;</span><br><span class="line">      defaults.putAll(Resources.getUrlAsProperties(url));</span><br><span class="line">    &#125;</span><br><span class="line">    Properties vars = configuration.getVariables();</span><br><span class="line">    <span class="keyword">if</span> (vars != <span class="keyword">null</span>) &#123;</span><br><span class="line">      defaults.putAll(vars);</span><br><span class="line">    &#125;</span><br><span class="line">    parser.setVariables(defaults);</span><br><span class="line">    configuration.setVariables(defaults);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="environments_u914D_u7F6E"><a href="#environments_u914D_u7F6E" class="headerlink" title="environments配置"></a>environments配置</h2><p>　　从下面的配置可以看出看出，environments元素节点可以配置多个environment子节点。这样可以多个环境，如开发环境和测试环境。给environments节点的default属性配置不同的值，这样mybatis在启动时会初始化相应的环境<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="tag">&lt;<span class="title">environments</span> <span class="attribute">default</span>=<span class="value">"development"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">environment</span> <span class="attribute">id</span>=<span class="value">"development"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="title">transactionManager</span> <span class="attribute">type</span>=<span class="value">"JDBC"</span> /&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置数据库连接信息 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="title">dataSource</span> <span class="attribute">type</span>=<span class="value">"POOLED"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"driver"</span> <span class="attribute">value</span>=<span class="value">"com.mysql.jdbc.Driver"</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"url"</span> <span class="attribute">value</span>=<span class="value">"jdbc:mysql://localhost:3306/mybatis"</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"username"</span> <span class="attribute">value</span>=<span class="value">"root"</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="title">property</span> <span class="attribute">name</span>=<span class="value">"password"</span> <span class="attribute">value</span>=<span class="value">"123456"</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="title">dataSource</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="title">environment</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">environments</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　下面给出environments节点的解析代码，并配上必要的注释<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">environmentsElement</span><span class="params">(XNode context)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (context != <span class="keyword">null</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (environment == <span class="keyword">null</span>) &#123;</span><br><span class="line">      <span class="comment">//获取需要使用的环境</span></span><br><span class="line">      environment = context.getStringAttribute(<span class="string">"default"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (XNode child : context.getChildren()) &#123;</span><br><span class="line">      String id = child.getStringAttribute(<span class="string">"id"</span>);</span><br><span class="line">      <span class="comment">//获取子节点，找到对应的enviroment子节点，并初始化</span></span><br><span class="line">      <span class="keyword">if</span> (isSpecifiedEnvironment(id)) &#123;</span><br><span class="line">        TransactionFactory txFactory = transactionManagerElement(child.evalNode(<span class="string">"transactionManager"</span>));</span><br><span class="line">        <span class="comment">//根据配置，生成相应的数据源类型，如连接池等</span></span><br><span class="line">        DataSourceFactory dsFactory = dataSourceElement(child.evalNode(<span class="string">"dataSource"</span>));</span><br><span class="line">        DataSource dataSource = dsFactory.getDataSource();</span><br><span class="line">        Environment.Builder environmentBuilder = <span class="keyword">new</span> Environment.Builder(id)</span><br><span class="line">            .transactionFactory(txFactory)</span><br><span class="line">            .dataSource(dataSource);</span><br><span class="line">        configuration.setEnvironment(environmentBuilder.build());</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="typeAliases_u914D_u7F6E"><a href="#typeAliases_u914D_u7F6E" class="headerlink" title="typeAliases配置"></a>typeAliases配置</h2><p>　　在mybatis-conf.xml的配置中，我们可以增加如下节点<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="title">typeAliases</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--</span><br><span class="line">    通过package, 可以直接指定package的名字， mybatis会自动扫描你指定包下面的javabean,</span><br><span class="line">    并且默认设置一个别名，默认的名字为： javabean 的首字母小写的非限定类名来作为它的别名。</span><br><span class="line">    也可在javabean 加上注解@Alias 来自定义别名， 例如： @Alias(user) </span><br><span class="line">    &lt;package name="com.dy.entity"/&gt;</span><br><span class="line">    --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="title">typeAlias</span> <span class="attribute">type</span>=<span class="value">"com.openim.test.mybatis.model.User"</span> <span class="attribute">alias</span>=<span class="value">"UserEntity"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="title">typeAliases</span>&gt;</span></span><br></pre></td></tr></table></figure></p>
<p>　　接着，我们新建一个如下测试方法，并打印信息<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="annotation">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run2</span><span class="params">()</span></span>&#123;</span><br><span class="line">        String resource = <span class="string">"mybatis-conf.xml"</span>;</span><br><span class="line">        InputStream is = Test1.class.getClassLoader().getResourceAsStream(resource);</span><br><span class="line">        SqlSessionFactory sessionFactory = <span class="keyword">new</span> SqlSessionFactoryBuilder().build(is);</span><br><span class="line">        </span><br><span class="line">        Map&lt;String, Class&lt;?&gt;&gt; typeMap = sessionFactory.getConfiguration().getTypeAliasRegistry().getTypeAliases();</span><br><span class="line">        <span class="keyword">for</span>(Map.Entry&lt;String, Class&lt;?&gt;&gt; entry: typeMap.entrySet()) &#123;</span><br><span class="line">            System.out.println(entry.getKey() + <span class="string">" ================&gt; "</span> + entry.getValue().getSimpleName());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p>
<p>　　接着，我们看看typeAliases的解析过程<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">typeAliasesElement</span><span class="params">(XNode parent)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (parent != <span class="keyword">null</span>) &#123;</span><br><span class="line">    <span class="keyword">for</span> (XNode child : parent.getChildren()) &#123;</span><br><span class="line">      <span class="keyword">if</span> (<span class="string">"package"</span>.equals(child.getName())) &#123;</span><br><span class="line">        <span class="comment">//如果是package节点。进入registerAliases方法，可以发现最后是由ResolverUtil类扫描package下的类</span></span><br><span class="line">        String typeAliasPackage = child.getStringAttribute(<span class="string">"name"</span>);</span><br><span class="line">        configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">//如果为非package节点，则获取类型和对应的别名</span></span><br><span class="line">        String alias = child.getStringAttribute(<span class="string">"alias"</span>);</span><br><span class="line">        String type = child.getStringAttribute(<span class="string">"type"</span>);</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">          <span class="comment">//注册别名</span></span><br><span class="line">          Class&lt;?&gt; clazz = Resources.classForName(type);</span><br><span class="line">          <span class="keyword">if</span> (alias == <span class="keyword">null</span>) &#123;</span><br><span class="line">            typeAliasRegistry.registerAlias(clazz);</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            typeAliasRegistry.registerAlias(alias, clazz);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (ClassNotFoundException e) &#123;</span><br><span class="line">          <span class="keyword">throw</span> <span class="keyword">new</span> BuilderException(<span class="string">"Error registering typeAlias for '"</span> + alias + <span class="string">"'. Cause: "</span> + e, e);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>　　实际使用中，基本上都是采用maven + mybatis generator插件自动生成对应的mapper、model和xml文件，所以这种别名的方式几乎用不到。此处便不再给出例子。在下一篇中，我们将实现自定义的TypeHander。接下来我们开始介绍ObjectFactory。</p>
<h2 id="ObjectFactory_u914D_u7F6E"><a href="#ObjectFactory_u914D_u7F6E" class="headerlink" title="ObjectFactory配置"></a>ObjectFactory配置</h2><p>　　在每次进行查询后，Mybatis都需要将查询结果转换成相应的实体类，这是他就是通过使用一个对象工厂（ObjectFactory）实例来完成。默认的对象工厂需要做的仅仅是实例化目标类，要么通过默认构造方法，要么在参数映射存在的时候通过参数构造方法来实例化。默认情况下，我们不需要配置，mybatis会调用默认实现的objectFactory。如果有重写 <em>ObjectFactory</em> 的需要，我们只需要继承DefaultObjectFactory（是ObjectFactory接口的实现类），并重写其方法即可。同时在mybatis-cong.xml的configuration节点下配置objectFactory子节点即可。此处不再做过多的介绍。</p>
<h2 id="u53C2_u8003_u6587_u7AE0"><a href="#u53C2_u8003_u6587_u7AE0" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="http://www.cnblogs.com/dongying/p/4036796.html" target="_blank" rel="external">http://www.cnblogs.com/dongying/p/4036796.html</a><br><a href="http://mybatis.org/mybatis-3/zh/sqlmap-xml.html" target="_blank" rel="external">http://mybatis.org/mybatis-3/zh/sqlmap-xml.html</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2015/12/09/mybatis/2.Mybatis系列之配置解析/" data-id="cijzzpv98007w1cfs2sdefm73" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/java/">java</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mybatis/">mybatis</a></li></ul>

    </footer>
  </div>
  
</article>


  
  
    <nav id="page-nav">
      <a class="extend prev" rel="prev" href="/page/11/">&laquo; Prev</a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/10/">10</a><a class="page-number" href="/page/11/">11</a><span class="page-number current">12</span><a class="page-number" href="/page/13/">13</a><a class="page-number" href="/page/14/">14</a><a class="page-number" href="/page/15/">15</a><a class="extend next" rel="next" href="/page/13/">Next &raquo;</a>
    </nav>
  
</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/cache/">cache</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/database/">database</a><span class="category-list-count">13</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/docker/">docker</a><span class="category-list-count">6</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/gis/">gis</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/git/">git</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/go/">go</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/gradle/">gradle</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/groovy/">groovy</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/hadoop/">hadoop</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/java/">java</a><span class="category-list-count">18</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/linux/">linux</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/log/">log</a><span class="category-list-count">11</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/mongodb/">mongodb</a><span class="category-list-count">14</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/mq/">mq</a><span class="category-list-count">6</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/mybatis/">mybatis</a><span class="category-list-count">9</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/netty/">netty</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/nginx/">nginx</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/nio/">nio</a><span class="category-list-count">19</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/nodejs/">nodejs</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/redis/">redis</a><span class="category-list-count">6</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/rpc/">rpc</a><span class="category-list-count">14</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/spring/">spring</a><span class="category-list-count">5</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/tomcat/">tomcat</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/zookeeper/">zookeeper</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/杂项/">杂项</a><span class="category-list-count">2</span></li></ul>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/aop/">aop</a><span class="tag-list-count">8</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/aspectj/">aspectj</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/cache/">cache</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/classloader/">classloader</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/common-loggings/">common-loggings</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/commonjs/">commonjs</a><span class="tag-list-count">4</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/database/">database</a><span class="tag-list-count">10</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/docker/">docker</a><span class="tag-list-count">6</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/dubbo/">dubbo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/fastdfs/">fastdfs</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/gclib/">gclib</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/geohash/">geohash</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/gis/">gis</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git/">git</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/go/">go</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/gradle/">gradle</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/groovy/">groovy</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/hadoop/">hadoop</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/hessisan/">hessisan</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/java/">java</a><span class="tag-list-count">48</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/javassist/">javassist</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/kafka/">kafka</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/linux/">linux</a><span class="tag-list-count">4</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/log/">log</a><span class="tag-list-count">11</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/log4j/">log4j</a><span class="tag-list-count">4</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/logback/">logback</a><span class="tag-list-count">5</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/map/">map</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/memecached/">memecached</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mina/">mina</a><span class="tag-list-count">5</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mongodb/">mongodb</a><span class="tag-list-count">14</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mq/">mq</a><span class="tag-list-count">6</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mqtt/">mqtt</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mybatis/">mybatis</a><span class="tag-list-count">9</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/netty/">netty</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nginx/">nginx</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nio/">nio</a><span class="tag-list-count">5</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nodejs/">nodejs</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/postgresql/">postgresql</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/protobuf/">protobuf</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/proxy/">proxy</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/push/">push</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/rabbitmq/">rabbitmq</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/redis/">redis</a><span class="tag-list-count">6</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/rpc/">rpc</a><span class="tag-list-count">14</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/sitemesh/">sitemesh</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/sld/">sld</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/slf4j/">slf4j</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/socket/">socket</a><span class="tag-list-count">7</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/spatialite-for-android/">spatialite for android</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/spi/">spi</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/spring/">spring</a><span class="tag-list-count">13</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/tomcat/">tomcat</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/transaction/">transaction</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/web/">web</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/xSocket/">xSocket</a><span class="tag-list-count">7</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/zbus/">zbus</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/zookeeper/">zookeeper</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/数据结构/">数据结构</a><span class="tag-list-count">2</span></li></ul>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/aop/" style="font-size: 15.38px;">aop</a> <a href="/tags/aspectj/" style="font-size: 11.54px;">aspectj</a> <a href="/tags/cache/" style="font-size: 11.54px;">cache</a> <a href="/tags/classloader/" style="font-size: 10px;">classloader</a> <a href="/tags/common-loggings/" style="font-size: 10px;">common-loggings</a> <a href="/tags/commonjs/" style="font-size: 12.31px;">commonjs</a> <a href="/tags/database/" style="font-size: 16.92px;">database</a> <a href="/tags/docker/" style="font-size: 13.85px;">docker</a> <a href="/tags/dubbo/" style="font-size: 10px;">dubbo</a> <a href="/tags/fastdfs/" style="font-size: 10px;">fastdfs</a> <a href="/tags/gclib/" style="font-size: 10.77px;">gclib</a> <a href="/tags/geohash/" style="font-size: 10px;">geohash</a> <a href="/tags/gis/" style="font-size: 10px;">gis</a> <a href="/tags/git/" style="font-size: 10.77px;">git</a> <a href="/tags/go/" style="font-size: 10px;">go</a> <a href="/tags/gradle/" style="font-size: 10px;">gradle</a> <a href="/tags/groovy/" style="font-size: 10px;">groovy</a> <a href="/tags/hadoop/" style="font-size: 10px;">hadoop</a> <a href="/tags/hessisan/" style="font-size: 11.54px;">hessisan</a> <a href="/tags/java/" style="font-size: 20px;">java</a> <a href="/tags/javassist/" style="font-size: 10px;">javassist</a> <a href="/tags/kafka/" style="font-size: 11.54px;">kafka</a> <a href="/tags/linux/" style="font-size: 12.31px;">linux</a> <a href="/tags/log/" style="font-size: 17.69px;">log</a> <a href="/tags/log4j/" style="font-size: 12.31px;">log4j</a> <a href="/tags/logback/" style="font-size: 13.08px;">logback</a> <a href="/tags/map/" style="font-size: 10px;">map</a> <a href="/tags/memecached/" style="font-size: 10.77px;">memecached</a> <a href="/tags/mina/" style="font-size: 13.08px;">mina</a> <a href="/tags/mongodb/" style="font-size: 19.23px;">mongodb</a> <a href="/tags/mq/" style="font-size: 13.85px;">mq</a> <a href="/tags/mqtt/" style="font-size: 10.77px;">mqtt</a> <a href="/tags/mybatis/" style="font-size: 16.15px;">mybatis</a> <a href="/tags/netty/" style="font-size: 10px;">netty</a> <a href="/tags/nginx/" style="font-size: 11.54px;">nginx</a> <a href="/tags/nio/" style="font-size: 13.08px;">nio</a> <a href="/tags/nodejs/" style="font-size: 10px;">nodejs</a> <a href="/tags/postgresql/" style="font-size: 10.77px;">postgresql</a> <a href="/tags/protobuf/" style="font-size: 10px;">protobuf</a> <a href="/tags/proxy/" style="font-size: 10px;">proxy</a> <a href="/tags/push/" style="font-size: 10px;">push</a> <a href="/tags/rabbitmq/" style="font-size: 11.54px;">rabbitmq</a> <a href="/tags/redis/" style="font-size: 13.85px;">redis</a> <a href="/tags/rpc/" style="font-size: 19.23px;">rpc</a> <a href="/tags/sitemesh/" style="font-size: 10px;">sitemesh</a> <a href="/tags/sld/" style="font-size: 10px;">sld</a> <a href="/tags/slf4j/" style="font-size: 10px;">slf4j</a> <a href="/tags/socket/" style="font-size: 14.62px;">socket</a> <a href="/tags/spatialite-for-android/" style="font-size: 10px;">spatialite for android</a> <a href="/tags/spi/" style="font-size: 10px;">spi</a> <a href="/tags/spring/" style="font-size: 18.46px;">spring</a> <a href="/tags/tomcat/" style="font-size: 10.77px;">tomcat</a> <a href="/tags/transaction/" style="font-size: 10px;">transaction</a> <a href="/tags/web/" style="font-size: 10px;">web</a> <a href="/tags/xSocket/" style="font-size: 14.62px;">xSocket</a> <a href="/tags/zbus/" style="font-size: 10px;">zbus</a> <a href="/tags/zookeeper/" style="font-size: 10.77px;">zookeeper</a> <a href="/tags/数据结构/" style="font-size: 10.77px;">数据结构</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/01/">January 2016</a><span class="archive-list-count">67</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/12/">December 2015</a><span class="archive-list-count">81</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/11/">November 2015</a><span class="archive-list-count">2</span></li></ul>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recents</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2016/01/30/资料/">(no title)</a>
          </li>
        
          <li>
            <a href="/2016/01/30/java/13.Classloader系列一/">ClassLoader系列一</a>
          </li>
        
          <li>
            <a href="/2016/01/29/hadoop/1.hadoop系列之源码编译/">hadoop系列一之源码编译</a>
          </li>
        
          <li>
            <a href="/2016/01/29/go/1.GO系列之入门/">Go系列一之入门</a>
          </li>
        
          <li>
            <a href="/2016/01/28/tomcat/2.tomcat性能优化/">tomcat性能优化</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2016 John Doe<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="http://libs.baidu.com/jquery/2.0.3/jquery.min.js"></script>


  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css" type="text/css">
  <script src="/fancybox/jquery.fancybox.pack.js" type="text/javascript"></script>


<script src="/js/script.js" type="text/javascript"></script>

  </div>
</body>
</html>